Rewrite死循环表现为访问卡顿、浏览器报重定向过多或500错误,access.log刷屏;核心线索是error_log中“rewrite or internal redirection cycle”提示及反复跳转的URI路径。
遇到 Rewrite 死循环,最直接的表现是访问瞬间卡住、浏览器报“重定向次数过多”,或服务端返回 500 错误,同时 access.log 疯狂刷屏、磁盘空间几秒内告急。这不是日志配置问题,而是请求在 Nginx 内部不断自我重写——关键要从现象反推路径链,再结合配置逻辑验证。
Nginx 在检测到内部跳转超限(默认 10 次)时,一定会在 error.log 中记录明确提示:
/index.php 或 /api/user
注意:很多“循环”其实是假象。继续往下查,如果看到 Permission denied 或 No such file or directory,说明目标文件不可读或根本不存在,Nginx 因 fallback 失败反复尝试,也会表现为循环。
不依赖日志,直接观察响应头是否来回跳:
curl -I http://your-domain/some-path
Location: https://... 且地址在两个值之间反复切换(如 A→B→A→B),说明 rewrite 已形成闭环permanent(301)和 redirect(302)标志,它们会让浏览器持续重发请求,放大问题普通 error log 只报结果,debug 日志才能还原完整路径链:
nginx.conf 的 http 块中临时添加:error_log /var/log/nginx/debug.log debug;
--with-debug(主流发行版通常默认支持)sudo tail -f /var/log/nginx/debug.log | grep -E "(rewrite|redirect|phase)"
*123456 rewrite phase: 3, "/old/test" -> "/new/test"
*123456 rewrite phase: 3, "/new/test" -> "/old/test" —— 跳转链一目了然
死循环高频发生于 last 和宽泛 location 的组合:
last 表示重写后重新走一遍全部 location 匹配流程;若新 URI 仍落入当前 location 范围,就会再次触发 rewritelocation /a/ { rewrite ^/a/(.*)$ /a/$1 last; } —— 改写前后都在 /a/ 下,必然循环• 改用 break(改写后留在当前 location 继续执行,不重匹配)
• 或收紧 location,如 location ^~ /a/ + 改写目标为 /b/$1
• 或优先用 return 301 替代 rewrite 实现外部跳转