rewrite_log on 本身不输出日志,必须配合 --with-debug 编译、error_log debug 级别及正确作用域配置才生效;还需结合 map、log_format 和 curl -v 验证执行路径。

要深度调试 Nginx 中复杂正则重写逻辑,rewrite_log on 是关键入口,但它本身不输出日志——必须配合 error_log 的调试级别才能生效,且仅在编译时启用了 --with-debug 才可用。
确保 Nginx 编译支持 debug 日志
普通发行版(如 Ubuntu apt、CentOS yum 安装)默认不带 debug 模块。需确认:
- 运行
nginx -V 2>&1 | grep -o with-debug,有输出才表示支持; - 若无,需从源码重新编译:
./configure --with-debug ... [其他原有选项]; - 注意:生产环境慎用 debug 模块,会显著降低性能并产生海量日志。
启用 rewrite 日志的完整配置组合
仅写 rewrite_log on 不起作用。必须同时满足三项:
- 全局或 server 块中开启:
rewrite_log on; - 指定 error_log 路径并设为
debug级别,例如:error_log /var/log/nginx/rewrite_debug.log debug; - 该 error_log 指令的作用域需覆盖到执行 rewrite 的 location(建议放在 http 或 server 级);
- 重启 Nginx 后,触发匹配 rewrite 的请求,日志中会出现类似:
2024/05/20 14:22:03 [debug] 12345#12345: *6789 "^/api/v(\d+)/(.+)$" matches "/api/v2/users", client: 127.0.0.1, ...
后续还会显示捕获组内容、替换结果、是否 break/redirect 等细节。
结合 map 和 log_format 观察变量变化
对多层嵌套或条件判断(如基于 $arg_ 或 $http_user_agent 的 rewrite),单靠 rewrite_log 可能不够直观。可辅助使用:
- 定义
map提取关键片段并打点:map $request_uri $debug_path { ~^/api/v(?<ver>\d+)/(?<rest>.+) "$ver|$rest"; default "-"; }</rest></ver> - 自定义
log_format记录中间变量:log_format debug_log '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$debug_path"'; - 在 access_log 中使用该格式,能快速比对原始请求与正则提取结果,避开 rewrite_log 的密集滚动干扰。
用 curl + -v 配合日志定位真实执行路径
Nginx rewrite 可能被多个 location 匹配、被 if 判断跳过、或受 last/break 标志影响执行流。调试时:
- 用
curl -v http://localhost/path查看实际返回状态和重定向头; - 对照 rewrite_log 时间戳,确认哪条 rewrite 规则真正生效(注意:log 中的 *号连接符对应同一请求);
- 若 rewrite 未触发,检查 location 匹配优先级(正则 location 优先于 prefix,但
^~会终止正则检查); - 临时在关键 location 内加
return 200 "matched: $uri";快速验证是否进入该块。
rewrite_log 不是开关即用的功能,而是 debug 生态的一环。它的真实价值在于把隐式匹配过程显性化,配合编译支持、日志分级和请求验证,才能让复杂正则重写变得可追溯、可证伪。


















