Nginx日志轮转失效:定位与恢复
access.log越写越大、旧日志一直没有压缩,或者文件已经改名却仍在增长,这几种情况不一定是同一个问题。先确认日志由谁写、哪条规则处理、定时任务是否真正执行,再决定修哪一处。
本文针对 Ubuntu 24.04 软件源安装的 Nginx,以及 logrotate 管理的文件日志。宝塔自带 Nginx、自编译实例和容器标准输出日志,应先确认各自的管理方式;Docker 日志可查看大小限制与清理教程。
一份日志只交给一套规则
先读主配置、软件包自带的 Nginx 规则和站点日志路径:
sudo sed -n '1,160p' /etc/logrotate.conf
sudo cat /etc/logrotate.d/nginx
sudo nginx -T 2>&1 | grep -E '^[[:space:]]*(access_log|error_log)[[:space:]]'
软件包的规则通常已经匹配 /var/log/nginx/*.log。新站点日志仍在这个目录且以 .log 结尾时,不要再另建一份规则处理同一个文件。自定义目录或其他文件名则需要检查是否真正被匹配。
nginx -T读取磁盘上的配置;刚改了日志路径,还应确认配置已成功重载。只看到配置文件里的新路径,不代表运行进程已经采用它。分享排障资料时,只提供必要的日志路径与错误,不公开整份配置。
先预演,弄清为什么这次没有轮转
sudo logrotate --debug /etc/logrotate.conf
--debug会解释匹配、状态和轮转判断,不改日志,也不更新状态文件。看见“无需轮转”不一定是失败,应结合输出和现有规则判断:
| 规则或现象 | 实际含义 |
|---|---|
daily、notifempty |
是否到期、日志是否为空都会影响本轮结果。 |
delaycompress |
配合 compress 时,刚轮转出的上一份通常留到下一轮才压缩;存在 .1 文件不等于压缩失败。 |
rotate 14 |
表示保留 14 轮旧文件,不保证恰好覆盖 14 个自然日。 |
maxsize 100M |
只在 logrotate 被执行时判断大小,不会实时监控并把文件严格限制在 100 MB 内。 |
遇到 duplicate log entry,检查是否两条规则覆盖同一日志,合并重复定义;不要用忽略重复来掩盖不清楚的归属。遇到目录权限或 su相关错误,应核对实际写入账号和父目录权限,不把整个日志目录递归改成 777。
配置能读,还要看谁在定时执行
systemctl list-timers --all logrotate.timer
systemctl cat logrotate.timer logrotate.service
sudo journalctl -u logrotate.service --since '7 days ago' --no-pager
sudo grep -F '/var/log/nginx/' /var/lib/logrotate/status
核对下一次执行时间、最近一次退出结果及日志中的具体错误。状态文件默认位于 /var/lib/logrotate/status;服务启动参数使用了 -s时,按那个路径检查。状态时间更新过,也不能代替实际文件验收,轮转过程中出错仍可能更新状态。
没有 timer 时,继续确认 /etc/cron.daily/logrotate或管理员实际配置的调度方式,别立即再加一条重复任务。需要更频繁地判断大小,应先评估当前调度覆盖的日志范围,再调整执行周期。修改 daily、hourly 或 maxsize 并不会自动改变调度频率。
旧文件还在写,检查重开日志这一步
轮转时只把文件改名,Nginx 可能仍拿着旧文件的打开句柄。正常规则需要在改名后通知当前实例重新打开日志;先查看规则里的 postrotate及其执行错误,不把原有脚本整段删掉重写。
已经确认轮转完成、问题来自重开失败,并且运行实例确实使用软件包的默认二进制和配置时,可以检查配置后通知它重开:
sudo /usr/sbin/nginx -t && sudo /usr/sbin/nginx -s reopen
reopen只重新打开运行中配置所使用的日志文件,不会加载新的站点配置。自编译、多实例或自定义 -c、-p的部署,要使用对应实例的参数,不能把信号发给另一套 Nginx。
不要直接删除或截断正在写的日志。copytruncate也不是通用补丁:复制与截断之间可能丢失记录。修复重开动作后,还要回到原轮转规则解决长期问题,不能靠每次手动执行维持。
验收看新请求写到了哪里
在允许的只读页面发起一次访问,再查看实际访问日志。下方域名、路径和日志文件均应替换为本机真实值:
curl --fail --show-error --max-time 10 https://www.example.com/healthz
sudo stat -c '%n inode=%i bytes=%s modified=%y' /var/log/nginx/access.log
sudo tail -n 5 /var/log/nginx/access.log
确认新请求写进当前日志,旧文件不再持续增长,并且下一次定时执行也成功。HTTP 返回错误时同样可能产生访问日志,页面是否健康和日志是否切换要分别判断;配置缓冲、条件记录或关闭了 access_log 的站点,也要按实际设置核对。
调小保留份数前,先另存需要留存的旧日志。磁盘已经接近满盘时,按磁盘占用排查先找增长来源与可用空间,别对全系统日志反复强制轮转。