排查Nginx location重定向死循环需先开启debug日志并设error_log为info级,通过access_log中高频301/302及error_log中“rewrite or internal redirection cycle”定位;再检查rewrite last是否引发重复location匹配,确保重写后URI落入无重写的终结块;同时核对proxy_pass末尾斜杠与location前缀一致性,避免代理路径错误导致后端重定向回环;最后用curl -v追踪Location头验证跳转路径。

排查 Nginx 中由 location 内部重定向(如 rewrite ... last 或 return 301/302 配合 proxy_pass)导致的死循环,核心是确认请求是否在多个 location 块之间反复跳转,且未最终匹配到能终止处理的块(如静态文件服务、真实后端代理或明确响应)。关键靠日志定位 + 配置逻辑梳理。
开启并分析 access_log 与 error_log
Nginx 默认不记录重定向路径细节,需主动增强日志。在 http 或 server 块中添加:
log_format debug '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time uct="$upstream_connect_time" '
'uht="$upstream_header_time" urt="$upstream_response_time" '
'uri="$uri" args="$args" host="$host"';再将该格式应用到 access 日志,并确保 error_log 级别为 info 或更高(如 error_log /var/log/nginx/error.log info;)。死循环发生时,access 日志中会高频出现相同 URI 的 301/302 响应,error 日志可能报 rewrite or internal redirection cycle —— 这是 Nginx 主动中断循环的明确信号。
检查 rewrite + last 的 location 匹配链
rewrite ... last 会发起一次新的 location 查找,极易引发循环。常见陷阱包括:
- rewrite 目标 URI 被另一个更宽泛的
location ^~或location /捕获,而该 location 又执行了同样的 rewrite - 使用
rewrite /old/ /new/ last;,但/new/仍匹配原 location 块(比如 location 是location /),导致无限重入 - 多个 location 块对同一路径做不同 rewrite,彼此“接力”跳转
解决方法:用 location = /exact/path 显式终结;或改用 rewrite ... break(不触发新 location 查找);或确保 rewrite 后的 URI 明确落入一个无 rewrite 的 location(如 location /static/ { root /data; })。
验证 proxy_pass 与 location 前缀的隐式重写
当 proxy_pass 值末尾带斜杠(如 proxy_pass http://backend/;),Nginx 会自动剥离 location 前缀。若配置为:
location /api/ {
proxy_pass http://backend/;
}则 GET /api/v1/user 会被代理为 http://backend/v1/user。但如果误写成:
location /api/ {
proxy_pass http://backend; # 缺少末尾 /
}则请求会变成 http://backend/api/v1/user —— 若后端又返回 302 重定向到 /api/...,而 Nginx 再次匹配到该 location,就可能形成循环。务必核对 proxy_pass 末尾斜杠与 location 前缀是否匹配。
用 curl -v + 请求头追踪实际跳转
在客户端用 curl -v http://your-domain/path 观察响应头中的 Location: 字段。如果看到连续多个 301/302 且 Location 值在几个相似路径间轮换(如 /a/ → /b/ → /a/),基本可判定是配置级循环。配合 Nginx 日志中对应时间点的 $uri 和 $args 字段,就能还原每次重定向前的原始请求路径,从而反推哪段 rewrite 或 proxy_pass 触发了它。











