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";
        }
    }
}

十二、总结 #

本章我们学习了:

  1. 访问日志:access_log配置和格式
  2. 错误日志:error_log配置和级别
  3. 日志格式:自定义格式和JSON格式
  4. 日志缓冲:buffer和flush配置
  5. 日志切割:logrotate配置
  6. 日志分离:按主机、路径、状态码分离
  7. 日志分析:命令行工具和GoAccess
  8. 日志转发:Syslog、ELK、Fluentd
  9. 日志安全:敏感信息过滤和权限控制

掌握日志管理后,让我们进入下一章,学习Rewrite重写!

最后更新:2026-03-27