nginx报“open() failed (2: no such file or directory)”错误,90%是配置误将api路径(如/api/state)当作静态文件处理,而非交由webman;根本原因在于try_files漏写$uri/、location ~ \.php$未覆盖非php请求,或代理与静态服务混用导致冲突。

Webman静态资源无法访问,90%的情况不是代码问题,而是Nginx没把请求正确交给Webman,或者Webman根本没收到静态文件路径——它压根不处理 /api/state 这类路径。
为什么Nginx报open() "/.../public/api/state" failed (2: No such file or directory)
这个错误日志看着像Webman的问题,其实是Nginx在“越权干活”:它误以为 /api/state 是个静态文件,试图直接从 public/ 目录下读取,但该路径实际是后端API接口,应由PHP进程处理。
- Nginx配置里用了
try_files $uri $uri/ /index.php?$query_string;但漏了$uri/后的 fallback,或写成了try_files $uri /index.php?$query_string;(少一个$uri/),导致目录型路径(如/api/)被跳过,直接 fallback 到/index.php,而部分旧版Nginx对这种写法解析异常 - 更常见的是:Nginx
location ~ \.php$块没覆盖到根路径下的非PHP请求,却把/api/xxx这类路径也扔进了静态文件查找逻辑 - 如果你用的是反向代理(比如指向
127.0.0.1:39003),那Nginx根本不会碰public/目录——此时报错说明你混用了代理和静态服务,配置冲突
Webman的public/目录到底谁在读?
答案取决于你如何部署:
Webman 2.2.0版本强化了 TCP/UDP 服务支持,优化路由组管理,并增强异步任务处理能力。结合协程与连接池技术,Webman 能轻松应对高并发场景,适用于网站、接口服务、即时通讯、物联网及游戏开发,兼具高性能、灵活扩展与稳定可靠,是多场景 PHP 服务开发的理想选择。
- **直接运行 Webman(如
php webman start)**:Webman内置的静态中间件app/middleware/StaticFile.php负责响应/upload/avatar.png这类请求,前提是config/static.php中enable为true,且请求路径能匹配到public/下真实存在的文件 - **Nginx + PHP-FPM 部署**:Nginx 应直接服务
public/下的静态文件,PHP-FPM 只处理.php请求;此时config/static.php的enable必须为false,否则 Webman 会重复尝试处理已由 Nginx 返回的静态响应,徒增开销 - **Nginx 反向代理到 Webman HTTP Server(如 39003 端口)**:所有请求(包括静态)都转发给 Webman 进程,此时必须开启
config/static.php的enable,且确保public_path()指向正确物理路径(检查support/helpers.php)
权限与路径修复的实操要点
别急着改 chmod 777——多数权限问题其实出在用户组和 SELinux 上:
- 确认 Webman 进程(或 PHP-FPM worker)运行用户(如
www-data或nginx)对public/目录有rx权限,对public/upload/等可写目录有rwx权限;执行ls -ld public public/upload查看 - 如果服务器启用了 SELinux(常见于 CentOS/RHEL),即使权限数字全对,也会被拦截;临时验证:执行
setenforce 0,再试访问;若恢复则需打标:chcon -R -t httpd_sys_content_t public/(只读)或httpd_sys_rw_content_t(可写) - 修改
public_path()时,不要拼接字符串,用__DIR__ . '/../../public'这类硬路径易出错;推荐用dirname(__DIR__, 2) . '/public'或直接定义常量define('PUBLIC_PATH', __DIR__ . '/../public'); -
webman-admin 插件的静态资源默认放在插件自己的
public/目录(如plugin/webman-admin/public/),不是主项目的public/app/——这点文档明确写了,但很多人手动把文件拷进主项目public/app/,结果白忙活
最易被忽略的一点:Webman 的静态中间件默认不处理以 . 开头的路径(如 /.git),但如果你加了自定义规则(比如禁止 /.env),一不小心可能把 /favicon.ico 或 /robots.txt 也拦掉了——检查 app/middleware/StaticFile.php 里的 strpos($request->path(), '/.') 是否过度匹配。










