Nginx 日志中“-”是变量值为空时的默认填充符,并非未记录;常见空值变量包括 $remote_user(未启用认证)、$http_referer(直接访问或隐私策略清空)、$http_user_agent(扫描器或代理丢失)、$http_x_forwarded_for(无上游代理透传)等。

Nginx 日志中频繁出现一连串的短横线(-),比如 - - [..] "GET / HTTP/1.1" 200 612 "-" "-",根本原因不是“没记录”,而是对应变量值为空或未获取到时,Nginx 默认用 - 填充。这不是 bug,是设计行为——但大量 - 往往意味着关键信息缺失,影响排查和分析。
哪些变量容易为空?为什么?
以下变量在常见场景下极易为空,从而输出 -:
- $remote_user:仅当启用 HTTP Basic Auth 且用户成功认证时才有值;未配置 auth 或匿名访问时恒为空
- $http_referer:直接输入 URL、书签访问、HTTPS→HTTP 跳转、部分隐私浏览器(如 Safari 智能防跟踪)会主动清空 referer
- $http_user_agent:极少数恶意扫描器或自定义脚本可能省略 UA;某些代理或 CDN 透传不全时也可能丢失
- $http_x_forwarded_for:仅当上游明确添加该头才存在;若 Nginx 是首层服务且无反向代理,该变量始终为空
- $request_time / $upstream_response_time:在 error_log 或某些异常阶段(如连接中断)可能未完成赋值,日志中显示为 -
如何让空值更可控、更可读?
不能删掉变量,但可以替换默认的 -,提升日志语义清晰度:
- 用空字符串替代:
"$http_referer"→"${http_referer:-}"(注意引号保留,否则语法错误) - 用占位符替代:
"${http_user_agent:-[no-ua]}",便于 grep 或日志系统识别 - 对 IP 类变量做兜底:
${remote_addr:-0.0.0.0}或${http_x_forwarded_for:-direct} - 注意:仅
log_format中支持这种 bash 风格的默认值语法(Nginx 1.11.8+),旧版本需靠 Lua 或 map 模块模拟
真正减少 - 的实用策略
与其后期替换,不如从源头减少空值产生:
- 确保前端代理(如 CDN、LB)正确透传
X-Forwarded-For和User-Agent,并在 Nginx 中用set_real_ip_from+real_ip_header正确提取真实客户端 IP - 在 server 或 location 块中显式设置缺失头:
proxy_set_header Referer $http_referer;(避免 upstream 丢弃) - 对静态资源请求(js/css/png 等)关闭 access_log,避免大量无业务价值的 - 日志冲淡关键请求
- 使用
map指令预处理变量:map $http_user_agent $ua_clean { "" "[empty]"; default $http_user_agent; }
然后在 log_format 中用$ua_clean替代原始变量
检查与验证方法
快速确认当前日志中 - 的分布和成因:
- 统计各字段空值比例:
awk '{print $1,$2,$4,$9,$10}' /var/log/nginx/access.log | head -10000 | sort | uniq -c | sort -nr - 抓取典型空 referer 请求:
grep '"-" "$http_user_agent"' /var/log/nginx/access.log | head -5 - 开启调试日志临时验证:
error_log /var/log/nginx/debug.log debug;(仅测试环境,性能开销大)


















