nginx 返回404的核心是确认实际查找路径与文件真实存在性:先用nginx -t查生效root,注意location内root会覆盖server级配置且路径拼接逻辑易错;再手动拼出物理路径并用ls验证是否存在、权限是否足够(含selinux上下文);spa需配置try_files兜底。

排查 Nginx 使用 root 指令访问静态资源返回 404,核心是搞清“Nginx 实际去哪找文件”和“它找的路径是否真有这个文件”。问题往往不出在“没放文件”,而出在“它压根没去你认为的地方找”。
确认 root 路径是否被 location 覆盖
Nginx 的 root 指令作用域很关键:server 块里的 root 是默认值,但只要某个 location 块里也写了 root,就会覆盖 server 级的配置,且只对这个 location 生效。
- 用
nginx -t检查语法后,再执行nginx -T(大写 T),它会输出合并后的完整生效配置,直接搜location /xxx和里面的root,看实际生效的是哪个路径 - 特别注意:如果 location 带前缀(比如
location /api/),而你在里面写root /var/www,Nginx 就会拼出/var/www/api/xxx去找文件 —— 这通常不是你想要的 - 解决办法:要么把 root 放到 server 块(统一根目录),要么在带前缀的 location 里改用 alias(它会替换掉 location 匹配部分)
验证 Nginx 拼出来的物理路径是否真实存在
root 不是“直接映射”,而是“拼接路径”。例如:
配置 location /images/ { root /mnt/upload; },访问 /images/logo.png,Nginx 实际查找的是 /mnt/upload/images/logo.png。
- 打开 access.log,找到那条 404 请求,记下 URI(如
/css/app.css) - 根据对应 location 的 root 值,手动拼出完整路径(如 root 是
/var/www/html→ 拼成/var/www/html/css/app.css) - 用
ls -l直接检查这个完整路径是否存在、文件名大小写是否一致(Linux 区分大小写) - 常见陷阱:前端打包后文件名带哈希(如
app.a1b2c3.js),但 HTML 里引用的还是旧名字,导致 404
检查权限与 SELinux(容易被忽略)
路径拼对了、文件也存在,依然 404?可能是“看得见,读不了”。
- 用
ps aux | grep nginx查看 worker 进程运行用户(通常是www-data或nginx) - 执行
sudo -u www-data ls -l /你拼出的完整路径,看是否能列出文件;如果提示 permission denied,说明权限不够 - 给目录加执行权限(
x)、文件加读权限(r):chmod 755 /var/www/html && chmod 644 /var/www/html/index.html - 若系统启用了 SELinux(如 CentOS/RHEL),用
ls -Z查看上下文,确保目录标记为httpd_sys_content_t,否则需用chcon -R -t httpd_sys_content_t /var/www/html
SPA 刷新 404 的特殊处理
Vue/React 等单页应用,首页能打开,一刷新就 404,不是 root 配错了,而是路由模式(history)需要 Nginx 主动兜底。
- 确保 location / 块里有
try_files $uri $uri/ /index.html; - 这行的意思是:先按 URI 找真实文件(如
/about→ 找/about文件或目录),找不到就返回/index.html,让前端 JS 自己解析路由 - 不要在 location / 里用 alias,alias 不能用于根路径;root + try_files 是标准解法
- index 指令也要配合,比如
index index.html;,确保默认返回正确入口文件











