要让nginx日志成为“故障侦察兵”,需配置含耗时分层(如$request_time、$upstream_response_time)、上下文标识(如$http_x_forwarded_for、$server_name)和安全标记(如$acl_tag)的结构化格式,按意图分流至不同文件,并建立“客户端→后端→nginx自身”的三层排查路径,同时严格管控日志权限与轮转安全。

要让 Nginx 日志真正成为“故障侦察兵”,不能只靠 tail -f access.log 硬盯。关键在于:日志得能说话,排查得有路径,审计得可追溯。
设计能“破案”的日志格式
默认的 combined 格式只够看热闹,查问题常缺关键线索。一个生产级日志至少应包含三类信息:
-
耗时分层数据:用
$request_time(Nginx 总耗时)、$upstream_response_time(后端处理耗时)、$upstream_connect_time(建连耗时)区分慢在哪儿 -
上下文标识:加入
$upstream_addr(实际转发到的后端 IP)、$http_x_forwarded_for(真实客户端 IP)、$server_name(匹配的虚拟主机) -
安全与控制标记:通过
map指令预设$acl_tag(如 internal / blocked_ip / scanner),再写入日志,让拦截、认证、扫描行为一目了然
推荐 JSON 格式(便于 ELK 解析)或竖线分隔格式(便于 awk/grep 快速提取):
log_format audit '|$time_iso8601|$remote_addr|$http_x_forwarded_for|$host|$request_method|$uri|$status|$body_bytes_sent|$request_time|$upstream_response_time|$upstream_addr|$upstream_status|$http_user_agent|$acl_tag|';按意图分离日志文件
把所有请求混在一个文件里,等于把报警器和背景噪音放一起听。应按事件性质分流记录:
- 所有访问统一记入
/var/log/nginx/access.log(主审计源) - 拦截请求(403)单独进
/var/log/nginx/deny.log,配合log_if $status = 403 - 认证失败(401)进
/var/log/nginx/auth_fail.log - HTTPS 协商详情仅在 443 server 块中启用专用
ssl_audit格式,记录$ssl_protocol、$ssl_cipher、$ssl_server_name
分离后,查某类问题只需聚焦单个文件,避免海量无关日志干扰判断。
建立结构化排查路径
看到告警别急着翻日志,先问三个问题,再对应查:
-
是不是客户端侧问题? 查 499(Client Closed Request):高频出现说明前端超时设置过短、用户频繁刷新或爬虫试探;结合
$http_user_agent和$remote_addr判断是否为异常来源 -
是不是后端服务拖慢? 查
$upstream_response_time明显大于$request_time的请求,再比对$upstream_status是否大量出现 5xx 或超时(-) -
是不是 Nginx 自身异常? 看
error.log中 warn 及以上级别日志:连接拒绝(Connection refused)、上游不可达(no live upstreams)、worker 进程异常退出等,直接指向配置或资源瓶颈
加固日志全链路安全性
日志本身含敏感信息(IP、URL、UA、认证状态),必须闭环管控:
-
权限收紧:日志目录
/var/log/nginx/设为750,属主root:adm;日志文件设为640,禁止其他用户读取 -
配置同步防护:
/etc/nginx/目录设为750,子配置640,防止恶意 include 注入 -
轮转不丢权限:用 logrotate 时务必配置
create 640 root adm,避免新切日志继承错误权限 -
缓冲与刷新平衡:access_log 启用
buffer=32k flush=5s,兼顾性能与故障时日志完整性











