Nginx日志管理 #
一、日志概述 #
Nginx提供两种主要日志:
- 访问日志(access_log):记录所有请求
- 错误日志(error_log):记录错误和诊断信息
二、访问日志 #
2.1 基本配置 #
nginx
http {
access_log /var/log/nginx/access.log;
}
2.2 指定日志格式 #
nginx
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent"';
access_log /var/log/nginx/access.log main;
}
2.3 关闭访问日志 #
nginx
location /health {
access_log off;
return 200 "OK";
}
2.4 条件日志 #
nginx
map $status $loggable {
~^[23] 0;
default 1;
}
server {
access_log /var/log/nginx/access.log combined if=$loggable;
}
三、日志格式 #
3.1 预定义格式 #
combined格式(默认):
nginx
log_format combined '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
common格式:
nginx
log_format common '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent';
3.2 自定义格式 #
nginx
log_format custom '$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"';
3.3 JSON格式 #
nginx
log_format json escape=json '{'
'"time":"$time_iso8601",'
'"remote_addr":"$remote_addr",'
'"remote_user":"$remote_user",'
'"request":"$request",'
'"status":"$status",'
'"body_bytes_sent":"$body_bytes_sent",'
'"request_time":"$request_time",'
'"http_referrer":"$http_referer",'
'"http_user_agent":"$http_user_agent",'
'"http_x_forwarded_for":"$http_x_forwarded_for",'
'"upstream_addr":"$upstream_addr",'
'"upstream_status":"$upstream_status",'
'"upstream_response_time":"$upstream_response_time",'
'"ssl_protocol":"$ssl_protocol",'
'"ssl_cipher":"$ssl_cipher"'
'}';
access_log /var/log/nginx/access.json json;
3.4 常用变量 #
| 变量 | 说明 |
|---|---|
| $remote_addr | 客户端IP |
| $remote_user | 认证用户名 |
| $time_local | 本地时间 |
| $time_iso8601 | ISO格式时间 |
| $request | 请求行 |
| $request_method | 请求方法 |
| $request_uri | 请求URI |
| $status | 响应状态码 |
| $body_bytes_sent | 响应体大小 |
| $request_time | 请求处理时间 |
| $http_referer | Referer头 |
| $http_user_agent | User-Agent头 |
| $http_x_forwarded_for | XFF头 |
| $upstream_addr | 上游服务器地址 |
| $upstream_status | 上游状态码 |
| $upstream_response_time | 上游响应时间 |
| $ssl_protocol | SSL协议 |
| $ssl_cipher | SSL密码套件 |
3.5 性能分析格式 #
nginx
log_format performance '$remote_addr - [$time_local] "$request" '
'$status $body_bytes_sent '
'rt=$request_time '
'uct="$upstream_connect_time" '
'uht="$upstream_header_time" '
'urt="$upstream_response_time" '
'cs=$connection_requests '
'bs=$bytes_sent';
四、错误日志 #
4.1 基本配置 #
nginx
error_log /var/log/nginx/error.log;
4.2 日志级别 #
nginx
error_log /var/log/nginx/error.log debug;
error_log /var/log/nginx/error.log info;
error_log /var/log/nginx/error.log notice;
error_log /var/log/nginx/error.log warn;
error_log /var/log/nginx/error.log error;
error_log /var/log/nginx/error.log crit;
error_log /var/log/nginx/error.log alert;
error_log /var/log/nginx/error.log emerg;
级别从低到高:debug < info < notice < warn < error < crit < alert < emerg
4.3 关闭错误日志 #
nginx
error_log /dev/null;
4.4 不同级别配置 #
nginx
http {
error_log /var/log/nginx/error.log warn;
server {
error_log /var/log/nginx/example.error.log info;
location /api/ {
error_log /var/log/nginx/api.error.log debug;
}
}
}
五、日志缓冲 #
5.1 启用缓冲 #
nginx
access_log /var/log/nginx/access.log combined buffer=32k;
5.2 刷新时间 #
nginx
access_log /var/log/nginx/access.log combined buffer=32k flush=5s;
5.3 参数说明 #
| 参数 | 说明 |
|---|---|
| buffer | 缓冲区大小 |
| flush | 刷新间隔 |
| gzip | 压缩日志 |
5.4 压缩日志 #
nginx
access_log /var/log/nginx/access.log combined buffer=32k flush=5s gzip=5;
六、日志切割 #
6.1 手动切割 #
bash
mv /var/log/nginx/access.log /var/log/nginx/access.$(date +%Y%m%d).log
nginx -s reopen
6.2 使用logrotate #
创建 /etc/logrotate.d/nginx:
text
/var/log/nginx/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 0640 nginx adm
sharedscripts
dateext
dateformat -%Y%m%d
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid)
endscript
}
6.3 logrotate参数说明 #
| 参数 | 说明 |
|---|---|
| daily | 每天切割 |
| weekly | 每周切割 |
| monthly | 每月切割 |
| rotate N | 保留N个备份 |
| compress | 压缩旧日志 |
| delaycompress | 延迟压缩 |
| missingok | 日志不存在不报错 |
| notifempty | 空日志不切割 |
| create | 创建新日志文件权限 |
| sharedscripts | 所有日志切割后执行一次脚本 |
| postrotate | 切割后执行的脚本 |
6.4 测试logrotate #
bash
logrotate -d /etc/logrotate.d/nginx
logrotate -f /etc/logrotate.d/nginx
6.5 自定义切割脚本 #
bash
#!/bin/bash
LOG_DIR="/var/log/nginx"
DATE=$(date +%Y%m%d)
KEEP_DAYS=30
cd $LOG_DIR
for log in *.log; do
if [ -f "$log" ]; then
mv "$log" "${log}.$DATE"
fi
done
nginx -s reopen
find $LOG_DIR -name "*.log.*" -mtime +$KEEP_DAYS -delete
gzip ${LOG_DIR}/*.log.${DATE} 2>/dev/null
七、日志分离 #
7.1 按虚拟主机分离 #
nginx
server {
server_name site1.example.com;
access_log /var/log/nginx/site1.access.log;
error_log /var/log/nginx/site1.error.log;
}
server {
server_name site2.example.com;
access_log /var/log/nginx/site2.access.log;
error_log /var/log/nginx/site2.error.log;
}
7.2 按路径分离 #
nginx
server {
location /api/ {
access_log /var/log/nginx/api.access.log;
proxy_pass http://backend;
}
location /static/ {
access_log /var/log/nginx/static.access.log;
root /var/www/static;
}
}
7.3 按状态码分离 #
nginx
map $status $log_name {
default "access";
~^[23] "success";
~^4 "client_error";
~^5 "server_error";
}
server {
access_log /var/log/nginx/$log_name.log;
}
八、日志分析 #
8.1 基本统计 #
请求量统计:
bash
wc -l /var/log/nginx/access.log
独立IP数:
bash
awk '{print $1}' /var/log/nginx/access.log | sort | uniq | wc -l
状态码统计:
bash
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
请求量Top 10 IP:
bash
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
访问量Top 10 URL:
bash
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
8.2 使用GoAccess #
安装:
bash
sudo apt install goaccess
分析:
bash
goaccess /var/log/nginx/access.log -o report.html --log-format=COMBINED
实时分析:
bash
goaccess /var/log/nginx/access.log -o report.html --log-format=COMBINED --real-time-html
8.3 使用awk分析 #
平均响应时间:
bash
awk '{sum+=$NF; count++} END {print "avg:", sum/count, "total:", count}' /var/log/nginx/access.log
慢请求统计:
bash
awk '$NF > 1 {print $0}' /var/log/nginx/access.log | wc -l
流量统计:
bash
awk '{sum+=$10} END {print sum/1024/1024 " MB"}' /var/log/nginx/access.log
九、日志转发 #
9.1 转发到Syslog #
nginx
access_log syslog:server=192.168.1.100:514,facility=local7,tag=nginx,severity=info;
error_log syslog:server=192.168.1.100:514,facility=local7,tag=nginx,severity=error;
9.2 转发到ELK #
使用Filebeat:
yaml
filebeat.inputs:
- type: log
paths:
- /var/log/nginx/*.log
fields:
type: nginx
fields_under_root: true
output.elasticsearch:
hosts: ["localhost:9200"]
index: "nginx-%{+yyyy.MM.dd}"
9.3 转发到Fluentd #
xml
<source>
@type tail
path /var/log/nginx/access.log
pos_file /var/log/fluentd/nginx-access.pos
tag nginx.access
format nginx
</source>
<match nginx.access>
@type elasticsearch
host localhost
port 9200
index_name nginx-access
</match>
十、日志安全 #
10.1 敏感信息过滤 #
nginx
log_format filtered '$remote_addr - $remote_user [$time_local] '
'"$filtered_request" $status $body_bytes_sent';
map $request $filtered_request {
~*(password|token|key) "[FILTERED]";
default $request;
}
10.2 日志权限 #
bash
chown nginx:nginx /var/log/nginx
chmod 750 /var/log/nginx
chmod 640 /var/log/nginx/*.log
10.3 日志审计 #
nginx
log_format audit '$time_iso8601 $remote_addr $request_method $request_uri '
'$status $body_bytes_sent $http_referer $http_user_agent '
'$ssl_protocol $ssl_cipher';
location /admin/ {
access_log /var/log/nginx/audit.log audit;
root /var/www/admin;
}
十一、完整配置示例 #
nginx
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'rt=$request_time uct="$upstream_connect_time" '
'uht="$upstream_header_time" urt="$upstream_response_time"';
log_format json escape=json '{'
'"time":"$time_iso8601",'
'"remote_addr":"$remote_addr",'
'"request":"$request",'
'"status":"$status",'
'"body_bytes_sent":"$body_bytes_sent",'
'"request_time":"$request_time",'
'"upstream_response_time":"$upstream_response_time",'
'"http_referrer":"$http_referer",'
'"http_user_agent":"$http_user_agent"'
'}';
map $status $loggable {
~^[23] 0;
default 1;
}
access_log /var/log/nginx/access.log main buffer=32k flush=5s;
error_log /var/log/nginx/error.log warn;
server {
listen 80;
server_name example.com;
access_log /var/log/nginx/example.access.log main;
error_log /var/log/nginx/example.error.log info;
location / {
root /var/www/html;
}
location /api/ {
access_log /var/log/nginx/api.access.log json;
proxy_pass http://backend;
}
location /health {
access_log off;
return 200 "OK";
}
}
}
十二、总结 #
本章我们学习了:
- 访问日志:access_log配置和格式
- 错误日志:error_log配置和级别
- 日志格式:自定义格式和JSON格式
- 日志缓冲:buffer和flush配置
- 日志切割:logrotate配置
- 日志分离:按主机、路径、状态码分离
- 日志分析:命令行工具和GoAccess
- 日志转发:Syslog、ELK、Fluentd
- 日志安全:敏感信息过滤和权限控制
掌握日志管理后,让我们进入下一章,学习Rewrite重写!
最后更新:2026-03-27