nginx 中未定义变量(如 $undefined_var)会被视为空字符串,导致 rewrite 或 return 结果异常;可通过自定义 log_format 记录 $request_uri 与 $uri、使用 echo 模块输出变量值、map 映射判断、审查变量来源及启用 debug 日志定位问题。

当 Nginx 的 rewrite 或 return 指令中引用了未定义变量(比如 $undefined_var),Nginx 不会报错,而是将其视为空字符串,导致重写结果意外为空——例如本该跳转到 /user/123,却跳到了 / 或 404。这类问题隐蔽性强,需结合日志与调试手段定位。
检查 access_log 中的重写后 URI
Nginx 默认不记录重写后的 URI,但可通过自定义 log_format 把 $request_uri 和 $uri 同时记下:
-
$request_uri是原始请求路径(含 query string) -
$uri是重写后、进入 location 匹配前的路径(不含 query string)
在 http 块中添加:
log_format debug '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'req="$request_uri" uri="$uri" args="$args"'然后在 server 或 location 中启用:access_log /var/log/nginx/debug.log debug;。访问触发重写的 URL,观察日志里 uri= 是否为空或异常。
用 echo 模块或 stub_status 验证变量是否存在
官方 Nginx 不直接输出变量值,但可借助第三方模块 echo-nginx-module 快速验证:
- 安装含 echo 模块的 OpenResty,或编译时加入该模块
- 在对应 location 中加:
echo "var_a: $arg_id, var_b: $undefined_var, uri: $uri";
访问时直接看到各变量展开结果,未定义变量会显示为空,一目了然。若无法安装模块,可用 map + log_format 间接判断:定义一个 map 将可疑变量映射为标记值,再打日志。
审查 rewrite 规则中的变量来源
常见未定义变量来源包括:
- 拼写错误:如把
$arg_uid写成$arg_userid - 依赖的 map 或 set 指令未生效(比如写在错误作用域,或条件不满足)
- 使用了只在某些模块中定义的变量(如
$upstream_http_x_token在无 upstream 时为空) - query string 未开启解析:确保
rewrite前没有if ($args = "") { ... }类逻辑干扰
重点检查所有 $xxx 变量是否属于Nginx 核心变量,或已在配置中明确定义(如 set $my_var "value"; 或 map 块)。
启用 error_log 的 debug 级别辅助分析
debug 日志会记录 rewrite 执行过程,包括每条规则是否匹配、变量展开值、重写后路径:
- 临时在 server 块中加:
error_log /var/log/nginx/rewrite-debug.log debug; - 注意:debug 日志量极大,仅用于短时排查,切勿长期开启
- 搜索日志中的
rewrite(注意末尾空格)和using字样,可看到类似:
*10 rewrite ^/old/(.*)$ to /new/$1?, client: 127.0.0.1
若出现to /new/$undefined_var?,就暴露了问题











