404错误怎么排查出来?

文章导读
浏览器或接口返回 404,先别急着改路由。404 只是“资源没找到”的结果码,返回方可能是应用框架、nginx、CDN 边缘节点或对象存储。排查的第一步是拿证据:谁返回了 404、请求的原始 URI 是什么、请求有没有到达你以为的那一层。这三样确定下来,多数情况能判断出该改配置还是改代码。
📋 目录
  1. Ⅰ 404错误怎么排查出来呢苹果
  2. Ⅱ 404错误怎么排查出来呢视频
  3. Ⅲ 404错误先定位在哪一层
  4. Ⅳ 404错误:先看这四个位置
  5. Ⅴ 404错误:按可能性从高到低排除
A A

浏览器或接口返回 404,先别急着改路由。404 只是“资源没找到”的结果码,返回方可能是应用框架、nginx、CDN 边缘节点或对象存储。排查的第一步是拿证据:谁返回了 404、请求的原始 URI 是什么、请求有没有到达你以为的那一层。这三样确定下来,多数情况能判断出该改配置还是改代码。

404 排查的核心不是猜原因,而是确认返回方。先用 curl -sI 查看响应头里的 Server、Via、X-Cache,判断 404 出自哪一层,再到对应层的日志里按时间戳找到原始请求 URI 和状态码。请求没进 nginx 日志,问题在 CDN 或客户端;进了日志但文件不存在,看 root、alias 和发布目录;文件存在仍 404,才轮到重写规则和应用路由。改完配置用 nginx -T 确认最终生效内容并 reload,清理缓存只用于让新结果生效,不能替代修复。

404错误怎么排查出来呢苹果

在 iPhone、iPad 的 Safari 或 App 内 WebView 里出现 404,多数不是“苹果端不支持”,而是同一路径在桌面浏览器能打开,在移动端因为 UA 分支、路径大小写、中文未编码或客户端缓存走了另一条链路。这一步在整体排查里属于“确认 404 是否只发生在特定客户端”。

可核对的位置有三个:nginx access_log 里的 UA 字段、Safari 的网页检查器网络面板、用 curl 手动指定 UA 得到的响应。先在服务器上按 UA 过滤:

# combined 格式下状态码是 $9、UA 是 $12,先用 head -n 1 确认列位置
awk '$9==404' /var/log/nginx/access.log | grep -i 'iPhone\|iPad' | tail -n 20

再用同一路径手动发一次带移动端 UA 的请求,对比状态码:

curl -sI -A "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1" https://example.com/你的路径

UA 里的系统版本会随设备变化,应以自己设备上复制的请求头为准:iPhone 在“设置 → Safari 浏览器 → 高级”里打开网页检查器,再用 Mac 的 Safari 开发菜单连接设备查看请求。如果 curl 返回 200 而手机上仍是 404,优先怀疑客户端缓存与跳转链路,清除历史记录与网站数据后重开页面验证;如果 curl 也返回 404,说明与设备无关,回到服务端继续查。

404错误怎么排查出来?

404错误怎么排查出来呢视频

视频类 404 出现在播放器加载 .m3u8、.ts、.mp4 分片时,和页面 404 的形态不同:一次播放会产生大量请求,只有部分分片失败时播放列表本身仍是 200,用户看到的是卡住或黑屏。这一步在整体排查里属于“按资源类型定位失败的具体 URI”。

可核对的位置是浏览器开发者工具的网络面板(按状态码筛 404,记下完整请求路径),以及服务端 access_log 按后缀聚合:

awk '$9==404 {print $7}' /var/log/nginx/access.log \
  | grep -E '\.(m3u8|ts|mp4|flv|m4s)$' | sort | uniq -c | sort -rn | head -n 20

$9 是状态码只在 combined 这类默认格式下成立,列位置不对就换成实际的状态码列。失败分片集中在同一目录,通常是 m3u8 里写的是相对路径,播放器按播放列表所在目录解析,请求到的路径和文件实际存放目录对不上。请求带 token、expires 这类参数时,先确认签名是否过期、URL 参数有没有被二次编码。涉及对象存储或 CDN 时,可用 curl -r 0-1023 请求前 1KB 字节,观察 Range 请求的状态码与响应头,判断是回源配置还是文件本身缺失。

404错误先定位在哪一层

按下面顺序走,每层的判断依据都来自可直接观察的证据:

404错误怎么排查出来?
  • 客户端层:缓存了旧的跳转或 404。判断依据是同一 URL 换无痕窗口或其他设备能正常打开。
  • 接入层(CDN、负载均衡):响应头出现 X-Cache、Via、Age,Server 是 CDN 厂商标识。判断依据是响应头,不是页面外观。
  • Web 服务器层(nginx、Apache):404 页面是服务器默认错误页,access_log 里有对应请求记录。
  • 应用层(框架路由、重写规则):404 页面是框架自己的错误页,日志里有请求但没有匹配的路由。
  • 存储层(文件目录、对象存储、数据库):路由正确但目标资源不存在。判断依据是在服务器上 ls 该路径,或到控制台按完整 key 查对象。
curl -sI https://example.com/出问题的路径

重点看响应头里的 Server、Via、X-Cache、X-Cache-Lookup、Age、Location。带 CDN 标识就先去控制台看缓存与回源日志,别在 nginx 里反复改 location;只有 nginx 或 Apache 标识,再往下翻服务器日志。要绕开 CDN 和 DNS 直连源站验证,用 --resolve 固定解析:

curl -sI --resolve example.com:443:源站IP https://example.com/出问题的路径

直连源站返回 200、走域名返回 404,问题基本落在接入层的缓存或回源配置上。

404错误:先看这四个位置

  1. 日志:nginx 的 /var/log/nginx/access.log 与 error.log,实际路径以 nginx -T 输出里的 access_log 指令为准。用 grep ' 404 ' /var/log/nginx/access.log | tail -n 50 拿到时间、URI、UA、来源 IP;应用日志里搜同一时间点的路由未匹配记录。
  2. 命令输出:curl -sI 看状态码和响应头;curl -v 看请求实际发往哪个地址、是否被 301 跳走。要连续比对多个路径,用 curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' URL 只输出结果。
  3. 配置项:nginx 用 nginx -T | grep -n 'location\|root\|alias\|try_files\|rewrite' 看最终生效配置;Apache 看虚拟主机配置与 .htaccess 里的 RewriteRule;框架层用自带路由列表命令,例如 Laravel 的 php artisan route:list,具体命令按所用版本确认。
  4. 面板字段:CDN 或对象存储控制台的缓存规则、回源 URL 与回源 Host、URL 重写、静态网站托管的索引文档与错误文档、防盗链白名单。各厂商字段名不同,以控制台实际文案为准,修改前先把原值记下来。

日志和命令输出的优先级高于配置项。配置看起来没问题、请求却没打到这台机器,是最常见的误判来源。

404错误:按可能性从高到低排除

  1. 路径拼写、大小写、末尾斜杠不一致。动作:从 access_log 取出实际请求 URI,在服务器上 ls 对应路径比对,Linux 文件系统区分大小写。
  2. 发布目录与 root/alias 指向不一致。动作:在 nginx -T 里找当前 server 块的 root,再 ls 该目录确认目标文件是否存在。
  3. try_files 或 rewrite 写错。动作:临时注释掉可疑规则,nginx -t 通过后 reload,复测同一 URL。
  4. 应用路由未注册或请求方法不匹配。动作:查框架路由列表里是否有该路径及允许的方法,POST 打到只注册了 GET 的路由需要按框架规则单独确认。
  5. 接入层缓存了 404。动作:看响应头中 X-Cache 一类字段是否为命中,对该 URL 刷新或清除后再测;清除只让新结果生效,不等于修好成因。
  6. 鉴权中间件、防盗链主动返回 404。动作:用不带 Referer 或带合法凭证的请求对比状态码是否变化。
  7. 对象存储的 key 前缀、区域端点、存储桶权限配错。动作:在控制台按完整 key 搜索对象,确认对象存在且允许当前访问方式读取。

最容易踩的坑是把 alias 当 root 用。root 会把 location 匹配到的部分拼进路径,alias 是直接替换,location 与 alias 末尾是否带斜杠会改变最终拼接结果;改完必须用 nginx -T 看展开后的实际路径,并在服务器上按该路径 ls 验证。同类问题是机器上有多份配置、改的不是被 include 的那份,reload 后现象不变,同样靠 nginx -T 输出的完整配置确认改的是生效的那份。