$status是Nginx日志中记录HTTP响应状态码的关键变量,用于识别4xx/5xx异常请求;可通过map指令标记status_level、access_log if条件筛选异常日志,并结合upstream_status定位真实失败环节。

$status 是 Nginx 日志中记录 HTTP 响应状态码的关键变量,直接反映客户端请求的处理结果。要快速识别异常请求,核心就是利用它筛选出 4xx(客户端错误)和 5xx(服务端错误)响应。无需额外模块或复杂脚本,Nginx 自身日志配置 + 简单条件即可实现高效过滤。
在 log_format 中直接标记异常状态
通过在自定义日志格式里加入条件判断,让异常请求的日志更醒目,便于肉眼识别或后续 grep:
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time '
'"$upstream_status"'; # 记录上游真实状态码(如后端返回的 502)
<p>log_format error_marked '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time '
'"$upstream_status" '
'$(echo $status | awk "{print (/^4[0-9]{2}$|^5[0-9]{2}$/ ? \"ERR\" : \"OK\")}")';</p>更推荐用 Nginx 内置的 map 指令 实现轻量级标记(无需 shell):
map $status $status_level {
~^4[0-9]{2}$ "client_error";
~^5[0-9]{2}$ "server_error";
default "success";
}
<p>log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time $status_level';</p>- map 变量支持正则匹配,
~^4[0-9]{2}$精确匹配所有 4xx,~^5[0-9]{2}$匹配所有 5xx - 日志中新增
$status_level字段,值为client_error、server_error或success - 配合
grep "client_error\|server_error"即可秒筛异常请求
用 access_log 的 if 条件只记录异常请求
如果只想保留问题请求日志(节省磁盘、提升分析效率),可启用 access_log ... if= 条件写入:
map $status $loggable {
~^4[0-9]{2}$ 1;
~^5[0-9]{2}$ 1;
default 0;
}
<p>access_log /var/log/nginx/error_only.log main if=$loggable;</p>- 只有当
$loggable == 1时,该请求才写入error_only.log - 避免日志中混杂大量 200/304,排查时直击重点
- 注意:if 条件仅作用于 access_log,不影响 error_log 或其他指令
结合 upstream_status 分析真实失败环节
单独看 $status 有时会误导——比如 Nginx 自身返回 502,但后端可能已返回 500。这时需参考 $upstream_status:
-
$status == 502且$upstream_status == "-":Nginx 无法连接上游(网络/配置问题) -
$status == 500且$upstream_status == "500":后端应用内部报错 -
$status == 404且$upstream_status == "200":可能是 Nginx rewrite 规则误判,或后端实际返回了 200 但内容为“未找到”页面
建议在 log_format 中同时记录两者,对比分析能快速定位是网关层、代理层还是业务层的问题。
常见误判与注意事项
-
$status是 Nginx 最终返回给客户端的状态码,不是后端原始状态(除非使用 proxy_pass + proxy_intercept_errors off) - 499 状态码(Client Closed Request)属于 Nginx 自定义状态,表示客户端主动断开,虽属 4xx 但通常不视为服务异常,可根据需要排除:
~^[45][0-9]{2}$→~^[45][0-9]{2}$且!~^499$ - 日志中
$status始终为三位数字字符串,正则匹配务必加^和$锚定,避免误匹配 2400、5000 等非法值 - 修改 map 或 log_format 后需
nginx -t && nginx -s reload生效

















