Linux 运维 · 已发布教程
Nginx 日志轮转:旧文件还在增长,该查哪里?
日志改名后仍增长,通常要检查进程是否重新打开了文件。本文说明 Nginx 的 USR1、logrotate 配置、容量估算和容器日志的不同处理。
改了文件名,进程可能还在写旧文件
把 access.log 改成 access.log.1,再创建一个新的 access.log,旧文件却继续增长,这是 Nginx 日志轮转中常见的问题。进程已经打开的文件描述符仍指向旧文件,修改路径名称并不会自动把写入目标换掉。
Nginx 的做法是先改名,再向主进程发送 USR1,通知它重新打开日志。HUP 用于重载配置,不必为了切割日志重启整个服务。下面讨论直接安装在 Linux 主机上、写入普通文件的 Nginx;容器标准输出在后面另说。
先找已有规则,别让两套任务一起切
发行版安装包可能已经提供 logrotate 配置,管理面板也可能有自己的切割任务。新增规则之前,先找出实际日志路径、Nginx 运行身份和已有调度。同一个文件被两套任务处理,容易出现重复改名或压缩失败。
从 nginx -T 的输出中查看 access_log、error_log 和 pid。自定义站点可能把日志放在另一目录,也可能写入 syslog。输出可能包含内部域名和配置细节,不要原样贴到公开工单。
sudo nginx -T
ps -eo pid,ppid,user,args | grep '[n]ginx'
sudo ls -l /etc/logrotate.d/
systemctl list-timers --all改规则时,把路径和运行身份一并对上
下面这份配置适用于日志在 /var/log/nginx、系统存在 www-data 与 adm、命令位于 /usr/sbin/nginx 的环境。重新打开日志使用 /etc/nginx/nginx.conf;它必须与运行中实例的配置一致。自定义 prefix、独立实例或面板管理的 Nginx,不要直接套用。
优先调整现有规则,而不是另建一份处理同样路径的配置。create 设置新文件权限,sharedscripts 让这组日志只执行一次后置脚本。delaycompress 延后压缩刚轮转的文件,但不能代替重新打开日志,也不能修复后置脚本失败。
/var/log/nginx/*.log {
daily
maxsize 100M
rotate 14
missingok
notifempty
compress
delaycompress
create 0640 www-data adm
sharedscripts
postrotate
/usr/sbin/nginx -c /etc/nginx/nginx.conf -s reopen
endscript
}100M 不是文件的硬上限
logrotate 被调用时才检查条件。定时任务一天执行一次,日志在两次检查之间仍可能远超 100 MB。写入量大时,要同时考虑调用频率、压缩耗时和磁盘余量,不能只把 maxsize 改小。
rotate 14 保留的是轮转份数,不保证十四个自然日。一天切几次,覆盖的时间就会缩短。保留策略应按故障调查需要安排,磁盘则把活跃文件、待压缩文件和历史归档都算进去。
日志突然暴涨,先看内容:可能是流量增加,也可能是一个错误反复刷屏。扩容能暂时解决空间不足,但不会消除重复报错。
先看干跑输出,再做一次真实轮转
logrotate -d 显示判断过程,不实际轮转,也不更新状态文件。它适合查规则冲突、路径和语法,不能证明重新打开日志的命令已经执行成功。
规则确认以后,再选低流量时段对单个目标安排真实轮转。强制执行会改动日志,先保存原配置、确认归档空间与保留份数,不要首次就强制处理全系统规则。
轮转前后各发一个带不同路径标记的请求,看看前一个是否在归档中,后一个是否进入新的活跃日志。如果请求被 CDN 缓存拦住,源站不会留下对应记录,应选择确实抵达这台 Nginx 的测试路径。
sudo logrotate -d /etc/logrotate.confNginx 通常不需要 copytruncate
copytruncate 先复制,再截断原文件。在两步之间继续写入的内容可能丢失。它适合不能重新打开日志的程序,而 Nginx 已有对应机制,通常没必要为省一条信号命令承担这个代价。
直接清空日志也不是轮转:空间腾出来了,旧记录却没有保留,之后仍会继续增长。如果删除文件后 df 显示空间没有释放,检查是否仍有进程持有句柄,别立刻把所有 Nginx 进程结束掉。
容器标准输出由 Docker 管
容器中的 access log 若指向标准输出,日志会由 Docker 的日志驱动接收。宿主机的 /var/log/nginx 可能与它无关,这时复制一份普通文件轮转规则没有用。
Docker 默认 json-file 没有自动轮转限制,需要为日志驱动设置合适的策略,或按部署要求选择其他驱动。修改守护进程默认值,不会自动改变已创建容器的设置;重建应用前,先保存数据和部署配置。不要直接搬动或截断 Docker 内部管理的日志文件。
如果容器仍向挂载目录写普通文件,就继续按文件处理,但要明确由谁通知容器内的 Nginx 重新打开日志。
第二天再看一次定时任务
手动轮转成功后,查看定时任务的最近执行记录和下次时间。使用 cron 的系统查实际任务,使用 systemd timer 的系统查计时器与关联服务。没有调度进程的精简容器,仅放入配置文件不会自动执行。
隔一天看看旧文件是否压缩、新请求是否继续写入活跃文件,磁盘余量是否正常。把最近成功时间和日志增长量加到监控中,后续就容易区分流量突增与任务停跑。