Nginx 日志管理终极指南
一、自定义访问日志格式
nginx
http {
# 基础增强格式
log_format main_ext '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time uct="$upstream_connect_time" '
'uht="$upstream_header_time" urt="$upstream_response_time"';
# API专用格式
log_format api_fmt '$remote_addr - $http_x_user_id [$time_iso8601] '
'"$request_method $request_uri" $status '
'req_len=$request_length res_len=$bytes_sent '
'ups_addr=$upstream_addr cache_status=$upstream_cache_status';
# 安全审计格式
log_format security '$remote_addr - $http_x_forwarded_for '
'$ssl_protocol/$ssl_cipher '
'[$time_local] "$request" $status '
'user_agent="$http_user_agent"';
server {
access_log /var/log/nginx/access.log main_ext;
error_log /var/log/nginx/error.log warn;
}
}
场景说明:
- 电商平台:使用main_ext格式跟踪全链路时延
- 移动API服务:采用api_fmt记录用户ID和缓存状态
- 金融系统:security格式强化安全字段记录
易错点分析:
- 变量拼写错误:如误用
$upstream_response_time
为$upstream_resp_time
- 特殊字符处理:未加引号包裹包含空格的字段(如User-Agent)
- 时间格式混淆:
$time_local
与$time_iso8601
的时区差异 - 上游变量为空:当未使用upstream时记录
$upstream_connect_time
会显示-
二、日志分割方案深度配置
方案A:logrotate系统级方案
conf
# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
daily
rotate 30
missingok
compress
delaycompress
notifempty
dateext
dateformat -%Y%m%d%H
sharedscripts
postrotate
[ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid`
endscript
}
方案B:crontab自定义切割脚本
bash
#!/bin/bash
# /opt/scripts/nginx_logrotate.sh
BASE_LOG_DIR="/var/log/nginx"
DATE_TAG=$(date +%Y%m%d-%H%M)
PID_FILE="/var/run/nginx.pid"
# 切割访问日志
mv ${BASE_LOG_DIR}/access.log ${BASE_LOG_DIR}/access-${DATE_TAG}.log
mv ${BASE_LOG_DIR}/error.log ${BASE_LOG_DIR}/error-${DATE_TAG}.log
# 向Nginx主进程发送USR1信号
kill -USR1 $(cat ${PID_FILE})
# 压缩旧日志(保留7天)
find ${BASE_LOG_DIR} -name "*.log-*" -mtime +7 -exec gzip {} \;
多场景选择指南:
- 中小型站点:方案A(logrotate)简单高效
- 大型分布式系统:方案B可结合HDFS转储
- Kubernetes环境:需使用sidecar容器处理日志
关键参数解析:
compress
vsdelaycompress
:立即压缩与延迟压缩策略dateext
与dateformat
:控制日志文件名后缀格式maxsize
:达到指定大小时触发切割(如maxsize 1G
)
典型错误案例:
- 信号误用:使用
kill -HUP
导致全配置重载 - 权限问题:脚本执行后新日志文件属主变为root
- 时区混乱:crontab与Nginx配置时区不一致
- 存储泄漏:未设置rotate导致磁盘空间耗尽
三、高级日志管理技巧
动态日志分级:
nginx
map $status $loggable {
~^[23] 0;
default 1;
}
server {
access_log /var/log/nginx/combined.log main_ext if=$loggable;
}
多维度日志分离:
nginx
http {
log_format app_log '$remote_addr $http_x_userid $request';
split_clients $remote_addr $log_switch {
50% /var/log/nginx/app.log;
50% off;
}
server {
access_log $log_switch app_log;
}
}
Troubleshooting检查清单:
- 文件描述符检查:
lsof -p nginx_pid | grep log
- inode验证:
df -i /var/log
- 权限验证:
namei -l /path/to/new.log
- 信号处理验证:
strace -p nginx_pid -e trace=signal
四、性能优化建议
- 日志缓冲:
access_log /path/to/log combined buffer=32k flush=1m
- 异步写入:设置
open_log_file_cache max=1000 inactive=20s
- 日志采样:
access_log /path/to/log combined if=$log_sample
- 敏感信息过滤:使用map过滤信用卡号等敏感数据
五、云原生环境特别注意事项
- 容器日志:需挂载volume到宿主机
- 日志采集:对接Fluentd/Filebeat的配置模板
- 动态字段:处理K8s metadata(pod名称、namespace等)
- 日志分级:DEBUG级别日志的性能影响评估
通过以上配置方案和深度解析,可构建从单机到集群、从传统架构到云原生的完整日志管理体系。实际部署时应结合监控系统(如Prometheus)进行日志量趋势分析,动态调整切割策略。