关键是要查 error.log 中 open() 失败的错误码:13 表示 permission denied(403),2 表示 no such file(404);再逐级验证目标路径存在性、各级目录执行权限(x)、nginx worker 用户读取权限及 selinux 上下文。

排查 Nginx 中 root 或 alias 配置导致的“404”或“403”问题,关键不是先改配置,而是确认:Nginx 进程有没有权限读取它最终拼出来的那个文件路径。很多报错表面是 404(找不到),实则是 403(没权限),但 Nginx 默认不返回 403,只静默失败并记为 404。
看 error.log 里真实报错类型
打开 Nginx 的 error 日志(建议设为 error_log logs/error.log debug; 并重载),发起一次出错请求,查找类似这样的行:
-
*1 open() "/var/www/static/app.js" failed (13: Permission denied)→ 明确是权限拒绝(403) -
*1 open() "/var/www/static/app.js" failed (2: No such file or directory)→ 才是真 404
注意括号里的数字:13 是 Permission denied,2 是 No such file。这是最直接的判断依据。
检查文件系统路径是否存在且可访问
拿到日志中报错的完整路径(比如 /var/www/static/app.js),分三步验证:
- 用
ls -l /var/www/static/app.js看文件是否存在、属主属组是否合理 - 用
ls -ld /var/www /var/www/static确认每一级父目录都有 x 权限(否则 Nginx 进程无法进入目录) - 确认 Nginx 工作进程用户(如
nginx或www-data)对文件有 r 权限,对目录有 rx 权限
特别注意 SELinux 和容器环境
在 CentOS/RHEL 系统上,即使权限全开,SELinux 也可能拦截:
- 运行
ls -Z /var/www/static/app.js查看安全上下文,正常应为httpd_sys_content_t - 若显示
unconfined_u:object_r:user_home_t:s0等非 Web 相关类型,需修复:chcon -Rt httpd_sys_content_t /var/www/static
在 Docker 容器中,还要确认挂载卷时加了 :ro(只读)或用户映射(--user)是否导致权限降级。
验证 Nginx 进程实际运行身份
别假设配置文件里写的 user nginx; 就一定生效:
- 执行
ps aux | grep nginx,看 master 进程和 worker 进程的 USER 列是否一致 - 如果用了 systemd 启动,检查
systemctl show nginx | grep User,可能被 service 文件覆盖 - worker 进程权限必须能覆盖目标路径,不能只看 master











