应开启debug日志并配置定向access日志,结合named location与internal指令切断隐式递归,再用curl验证跳转链。

遇到“重写或内部重定向循环”引发的 500 错误,Nginx 默认错误日志往往只显示一句模糊提示,比如:
*123456 rewrite or internal redirection cycle while internally redirecting to "/xxx"这类错误本质是 location + try_files / rewrite / if 等指令组合不当,造成 Nginx 在内部反复跳转,最终触发保护性中断(默认最多 10 次)。要深度定位,不能只靠默认日志,需主动增强日志粒度和上下文。
开启 debug 级别错误日志
这是获取重定向路径链最直接的方式。普通 error 日志不记录每次跳转细节,必须启用 debug 级别:
- 编辑 /etc/nginx/nginx.conf,在
http块中添加或修改:
- 确保 Nginx 编译时启用了
--with-debug(主流发行版包通常已包含); - 重启前先测试:
sudo nginx -t; - 重启后复现问题,再执行:
sudo tail -f /var/log/nginx/error.log | grep -i "rewrite\|redirect\|cycle"; - 你会看到类似:
*123456 rewrite phase: 3, "/old" -> "/new"、*123456 http finalize request: 500的逐跳记录。
在关键 location 中添加自定义 access 日志
debug 日志量大且全局开启有性能影响,可对高风险 location(如含 try_files、rewrite、if)单独打标:
- 在对应 server 或 location 块中加入:
- 并在 http 块顶部定义变量(用于标记被重定向过的请求):
- 这样所有匹配 /api/ 或 /app/ 的请求,无论是否重定向,都会记入独立日志,便于比对原始 URI 和最终 fallback 路径;
- 配合
log_format加入$uri、$request_filename、$args等字段,能看清每次 rewrite 后的真实文件路径。
限制并捕获循环跳转次数
Nginx 默认最多 10 次内部重定向就报 500。可通过配置提前暴露问题点:
- 在 http 或 server 块中设置:
client_max_body_size 10M;
- 更重要的是,在出问题的 location 中显式控制 try_files 行为:
try_files $uri $uri/ @fallback;
}
location @fallback {
# 避免再次触发 try_files 循环
internal;
proxy_pass http://backend;
}
- 用 named location(@fallback)替代直接 fallback 到 /index.html,可切断隐式递归;
- 加上
internal指令,确保该 location 只能被内部重定向调用,防止外部绕过。
验证与收口:用 curl 模拟并观察响应头
日志只是线索,最终要确认是否真有循环。用 curl 查看实际跳转链:
- 执行:
curl -I -v http://your-domain.com/bad-path - 观察响应头中的
X-Redirect-Count(需自己加)或Location字段是否反复出现相同路径; - 更稳妥做法:在 Nginx 配置中临时插入 header 记录跳转次数:
if ($request_uri ~ ^/api/) {
set $redirect_count 1;
}
add_header X-Redirect-Count $redirect_count;
- 逐步增加条件,配合日志交叉验证哪一环开始失控。











