核心是规范日志格式使状态码稳定可提取,再用goaccess、shell或进阶分析工具按需聚合:先自定义log_format将$status前置并用“|”隔离,确保awk '{print $1}'精准提取;再用goaccess生成实时html报表;shell脚本做离线趋势分析;最后结合$upstream_status定位真实故障环节。

核心是让状态码成为可稳定提取的字段,再用工具按需聚合——不是直接解析原始 combined 日志,而是先规范日志格式,再选对工具链。
先让 $status 变成“好提取”的字段
默认 combined 格式中 $status 位置不固定,受 User-Agent 长度、引号嵌套等干扰,awk '{print $9}' 容易错位。必须在 nginx.conf 中自定义 log_format,把状态码前置并用强分隔符隔离:
- 推荐配置:
log_format status_log '$status | $remote_addr [$time_local] "$request" $body_bytes_sent "$http_referer" "$http_user_agent" $request_time $upstream_response_time $upstream_status'; - 启用该格式:
access_log /var/log/nginx/status.log status_log; - 重载配置:
nginx -t && nginx -s reload
这样每行开头就是纯数字状态码(如 200 | ...),awk '{print $1}' 就能 100% 准确提取,为后续分析打下基础。
用 GoAccess 快速生成可视化状态码报表
GoAccess 天然适配结构化日志,无需数据库或 Java 环境,一条命令即可输出带交互图表的 HTML 报表:
- 实时终端查看:
goaccess /var/log/nginx/status.log -f --log-format='%v %^ %^ %^ %^ %^ %^ %^ %^ %^' --date-format='%d/%b/%Y' --time-format='%H:%M:%S'(%v匹配首字段,即状态码) - 生成网页版:
goaccess /var/log/nginx/status.log --log-format='%v %^ %^ %^ %^ %^ %^ %^ %^ %^' --real-time-html --output=/var/www/html/status-report.html --ws-url=ws://localhost:7890 - 另起终端运行 WebSocket 服务:
goaccess --real-time-html --port=7890
打开网页后,“HTTP Status Codes”模块会自动统计各状态码占比、Top URL、访问时段分布,并支持点击下钻查看明细。
用 Shell 脚本做轻量级离线趋势分析
若只需每日汇总、发邮件或写入监控系统,Shell + awk 更轻便可靠:
- 统计昨日 5xx 占比:
awk '$1 ~ /^5[0-9]{2}$/ {c++} END {print "5xx rate: " c/NR*100 "%"}' /var/log/nginx/status.log.1 - 按小时列出 404 请求量:
awk '$1 == "404" {gsub(/\[/, "", $3); print substr($3, 1, 13)}' /var/log/nginx/status.log | sort | uniq -c - 导出 JSON 结构化指标:
echo "{\"date\":\"$(date -d 'yesterday' +%F)\",\"5xx_count\":$(awk '$1~/^5[0-9]{2}$/ {c++} END{print c+0}' status.log.1),\"499_count\":$(awk '$1==499{c++}END{print c+0}' status.log.1)}"
配合 cron 每日凌晨执行,结果可直接推送至钉钉、邮件或写入 Prometheus Pushgateway。
进阶:结合 upstream_status 定位真实故障环节
单看 $status 是表层结果。真正有价值的报表要关联 $upstream_status,区分是 Nginx 层问题还是后端问题:
-
$status=502 && $upstream_status="-"→ 后端未监听/网络不通 -
$status=502 && $upstream_status="500"→ 后端应用返回了错误 -
$status=504 && $upstream_status="-"→ 后端响应超时
在 log_format 中加入 $upstream_status 后,可用 awk 或 Python 脚本交叉统计,生成“后端健康度矩阵”,比单纯看 5xx 更具运维指导性。











