nginx日志管理

张开发
2026/4/13 12:33:55 15 分钟阅读

分享文章

nginx日志管理
在大多数 Linux 发行版如 Ubuntu, CentOS中Nginx 安装后的默认日志通常位于/var/log/nginx/目录下。默认配置主要包含两类文件访问日志 (access.log)记录每一个 HTTP 请求的详细信息。错误日志 (error.log)记录 Nginx 运行过程中的错误、警告及调试信息。你可以通过以下命令查看当前生效的日志配置路径sudo nginx -T | grep -E (access_log|error_log)核心日志解读1. 访问日志 (access_log)默认通常采用combined格式一条典型的日志如下192.168.1.100 - - [15/Dec/2023:14:30:22 0000] GET /api/users HTTP/1.1 200 1234 https://example.com Mozilla/5.0...字段含义关键作用$remote_addr客户端 IP识别访客来源封禁恶意 IP$time_local时间戳定位问题发生的时间点$request请求行查看请求方法 (GET/POST) 和 URI$status状态码核心指标(200 成功, 404 未找到, 500 服务器错误)$body_bytes_sent响应大小分析带宽消耗$http_user_agent用户代理识别浏览器、爬虫或恶意脚本2. 错误日志 (error_log)错误日志不仅记录错误还分等级。默认级别通常是error但在开发环境建议调至warn或info。级别排序由重到轻emerg(紧急) alertcriterrorwarnnoticeinfodebug。生产环境建议设置为warn级别既能捕获关键问题又避免日志量过大。如何优化 Nginx 日志默认的日志配置在低流量下尚可但在高并发场景下频繁的磁盘 I/O 会拖慢 Nginx 性能且日志文件过大会导致难以分析。以下是具体的优化策略1. 性能优化开启缓冲 (Buffering)默认情况下Nginx 是同步写入日志的。在高并发下每来一个请求就写一次磁盘会严重消耗 I/O 资源。优化方案开启buffer和flush。这意味着 Nginx 会先把日志存在内存里积攒到一定量如 32k或一定时间如 5分钟后再写入磁盘。# 优化后的 access_log 配置 access_log /var/log/nginx/access.log combined buffer32k flush5m;注意开启缓冲后日志会有几秒到几分钟的延迟这是为了性能做出的权衡。2. 内容优化过滤静态资源如果你的 Nginx 既做反向代理又托管静态文件图片、CSS、JS记录这些静态文件的访问日志通常是没必要的只会徒增磁盘压力。优化方案在location块中关闭特定文件的日志记录。# 对静态资源关闭日志 location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { access_log off; expires 30d; # 顺便加上缓存头 }3. 格式优化使用 JSON 格式默认的文本日志虽然人类可读但机器解析起来比较麻烦需要正则。现代日志分析系统如 ELK Stack更喜欢 JSON 格式。优化方案定义 JSON 格式的log_format。log_format json_combined escapejson { time_local:$time_local, remote_addr:$remote_addr, request:$request, status: $status, body_bytes_sent:$body_bytes_sent, http_user_agent:$http_user_agent }; access_log /var/log/nginx/access.log json_combined;错误日志在nginx.conf中配置非常简单error_log /var/log/nginx/error.log warn;第一部分日志文件的存储路径绝对路径。第二部分日志级别可选默认为error。关闭错误日志如果你想彻底关闭错误日志通常不推荐不能写error_log off;这会创建一个名为 off 的文件而是应该指向空设备error_log /dev/null;日志轮转Log Rotation日志轮转Log Rotation是服务器运维的“生命线”。如果没有它你的access.log可能会在几天内膨胀到几十 GB导致磁盘爆满、服务器宕机或者让你在排查问题时面对一个打都打不开的巨型文件。Linux 系统自带的logrotate工具是管理 Nginx 日志的标准方案。它不仅能自动切割日志还能压缩旧日志、删除过期文件并通知 Nginx 重新打开日志文件。以下是logrotate的配置详解、参数说明以及实战模板。️ 核心配置文件位置logrotate的配置通常分为两部分主配置文件/etc/logrotate.conf通常不需要改动它定义了全局默认值和定时任务。应用专属配置/etc/logrotate.d/目录我们在这里为 Nginx 创建独立配置。查看 Nginx 是否已有默认配置ls -l /etc/logrotate.d/nginx cat /etc/logrotate.d/nginx注大多数通过包管理器yum/apt安装的 Nginx 都会自带这个文件但默认保留天数可能较短如 7 天建议根据需求修改。 配置参数详解一个标准的 Nginx 日志轮转配置包含以下关键指令。你可以直接参考下表来理解每个参数的作用参数含义推荐值/说明daily轮转频率每天一次也可用weekly,monthly。rotate 30保留数量保留 30 个归档文件即 30 天超出的自动删除。compress压缩使用 gzip 压缩旧日志极大节省磁盘空间。delaycompress延迟压缩当天的日志不压缩方便运维直接查看昨天的日志。missingok忽略缺失如果日志文件不存在不报错直接跳过。notifempty空不转如果日志文件是空的0字节不进行轮转。create 0640 user group新建权限轮转后创建新文件设置权限和属主如nginx nginx或www-data adm。sharedscripts脚本优化如果有多个日志文件只执行一次postrotate脚本。postrotate...endscript核心动作轮转后执行的命令必须通知 Nginx 重开日志否则新日志无法写入。推荐配置模板实战版你可以直接编辑/etc/logrotate.d/nginx文件使用以下优化后的配置。注意请根据你的系统确认 Nginx 的运行用户CentOS 通常是nginxUbuntu 通常是www-data和 PID 文件路径。# 编辑配置文件 sudo vim /etc/logrotate.d/nginx复制以下内容1/var/log/nginx/*.log { 2 daily; # 每天切割 3 missingok; # 日志文件不存在也不报错 4 rotate 30; # 保留 30 天的日志 5 compress; # 压缩旧日志 6 delaycompress; # 延迟一天压缩保留最新归档为 .1 而非 .1.gz 7 notifempty; # 空文件不切割 8 create 0640 nginx nginx; # 创建新文件的权限和属主 (Ubuntu请改为 www-data adm) 9 sharedscripts; # 多个日志文件只运行一次脚本 10 postrotate; # 切割后执行的脚本 11 # 关键发送 USR1 信号给 Nginx告诉它重新打开日志文件 12 # 如果 Nginx 没收到信号它会继续往旧文件里写导致轮转失效 13 if [ -f /var/run/nginx.pid ]; then 14 kill -USR1 cat /var/run/nginx.pid 15 fi 16 endscript 17} 如何测试与验证配置写好后不要直接等第二天看效果建议立即进行测试。1. 调试模式模拟运行使用-d参数它只会打印出“如果我现在运行 logrotate 会发生什么”而不会真正执行切割。这是检查语法错误和路径问题的最佳方式。sudo logrotate -d /etc/logrotate.d/nginx观察输出如果没有报错且显示rotating pattern: /var/log/nginx/*.log说明配置基本正确。2. 强制切割立即执行使用-f参数强制立即执行一次轮转用于验证 Nginx 是否能正常接收信号并生成新日志。sudo logrotate -f /etc/logrotate.d/nginx3. 验证结果执行完强制切割后查看日志目录ls -lh /var/log/nginx/你应该能看到access.log一个新的、大小为 0 的文件。access.log.1刚才被切割出来的旧日志。access.log.2.gz之前被压缩的旧日志。⚠️ 常见坑与解决方案1. 切割后 Nginx 停止写入日志原因postrotate中的kill -USR1命令没有执行成功或者 PID 文件路径不对。排查检查/var/run/nginx.pid是否存在。如果不确定 PID 路径可以在 Nginx 配置中查看pid指令。解决确保postrotate脚本中的路径正确且kill命令有权限执行。2. 权限错误 (Permission denied)原因create指令指定的属主与实际 Nginx 运行用户不一致。解决CentOS/RHEL: 通常是create 0640 nginx nginxUbuntu/Debian: 通常是create 0640 www-data adm3. 日志没有被自动轮转原因系统的定时任务没开。解决logrotate依赖系统的cron或systemd timer。检查定时任务ls -l /etc/cron.daily/logrotate如果是 systemd 管理systemctl status logrotate.timer确保它是 active 的。 专家提示不要手动重命名日志文件千万不要用mv access.log access.log.bak这种方式来备份日志。因为 Nginx 进程仍然持有旧文件的句柄它会继续往那个被重命名的文件里写数据导致轮转机制彻底混乱。一定要用 logrotate。磁盘空间告急时的紧急清理如果磁盘满了不要直接rm正在写入的日志文件这不会释放空间。应该使用truncate -s 0 /var/log/nginx/access.log清空文件内容或者配置好 logrotate 后立即执行一次强制轮转。

更多文章