你的网站是不是被日志文件“撑爆”了?
磁盘突然告急?df -h一看,/var/log占了98%?
查了半天,发现一个 access.log 已经长到 40GB——而你连上周三的 404 错误都找不到。
日志轮转到底是什么?为什么非做不可?
日志轮转,就是让日志自己“按时下班、打包存档、腾出空位”。
它不复杂:每天(或每小时)把正在写的日志关掉,改个名字,压成 .gz,再新建一个空文件接着记。整个过程自动完成。
没它会怎样?
→ 磁盘越攒越多,直到某天 nginx 写不了日志,直接报错挂掉;
→ 查问题时翻不到三天前的日志——因为早被覆盖了;
→ 想分析流量高峰?抱歉,只有最新一小时的碎片。
真实场景:去年帮一家本地 SaaS 公司排查慢响应,发现他们 Apache 的 access.log 跑了半年没轮转,单文件超 80GB。一重启服务,光是打开日志文件就卡住 3 秒——这哪是记录访问,这是给服务器上刑。
主流的日志轮转方案有哪些?
首选 logrotate ——Linux 服务器上最稳、最熟、最不用操心的方案。它不是某个软件的插件,而是系统级工具,Nginx、Apache、自研 Python 服务、甚至你写的 shell 脚本日志,它全都能管。
Web 服务器自带的轮转(比如 Nginx 的 reopen_logs)也能用,但功能太简陋:不能压缩、不能按日期命名、没法设保留份数。真要靠它扛生产流量,等于拿订书机当电钻使。
至于容器环境?如果你用 Docker,别急着上 Fluentd。先确认一件事:你的应用是否真的必须“边写边轮转”?多数中小团队的 PHP/Node/Java 应用,老老实实用 logrotate 配合宿主机定时任务,更轻量、更可控、出问题更好 debug。
如何用 logrotate 配置一个“黄金标准”?
配置文件放在 /etc/logrotate.d/ 下,名字随便起(比如 nginx-access),内容如下:
/var/log/nginx/access.log {
daily
rotate 30
missingok
notifempty
compress
delaycompress
dateext
sharedscripts
create 0640 www-data www-data
postrotate
[ -f /run/nginx.pid ] && kill -USR1 $(cat /run/nginx.pid)
endscript
}
关键项直白解释:
daily:每天凌晨切一次;rotate 30:最多留 30 天的归档(access.log-20241001.gz这种);compress+delaycompress:旧日志压成.gz,但最新一份先留着明文,方便紧急排查;dateext:归档名带日期,不怕顺序乱;create 0640 www-data www-data:新日志文件一生成,权限和属主就设好,避免 nginx 写不进去;postrotate里的kill -USR1:通知 Nginx “换新本子记账”,不中断服务。
配置时最容易踩的坑是什么?
坑一:新日志文件 nginx 写不进去logrotate 默认用 root 创建文件,但 nginx 是 www-data 用户跑的。结果新日志属主是 root,权限 600,nginx 直接被拒之门外。
✅ 解法:加上 create 0640 www-data www-data,一步到位。
坑二:轮转后,日志还在往旧文件里写postrotate 脚本执行失败(比如 pid 文件路径错了),logrotate 不报错,但 nginx 没收到信号,继续往 access.log-20241001 这种已归档的文件里狂写。
✅ 解法:手动跑一遍 sudo logrotate -f /etc/logrotate.d/nginx-access,然后立刻 ls -l /var/log/nginx/,确认新 access.log 出现且大小在涨。
坑三:磁盘还是满了
你以为 rotate 7 + compress 就只占 7 份空间?忘了 delaycompress 会让当天的旧日志先留明文,加上压缩延迟,高峰期可能同时存在 access.log、access.log-20241001、access.log-20241001.gz 三份。
✅ 解法:给 /var/log 单独划个分区,或者至少留出 2 倍于日均日志量的缓冲空间。
怎么验证和监控日志轮转是否正常?
别等出事才想起来看。配置完马上验证:
- 先用
-d参数“纸上谈兵”:它会打印每一步打算做什么,语法错、路径错、权限错,全给你标出来。sudo logrotate -d /etc/logrotate.d/nginx-access - 再用
-f强制执行一次:然后sudo logrotate -f /etc/logrotate.d/nginx-accessls -lt /var/log/nginx/,看到access.log-YYYYMMDD.gz生成,且新的access.log时间戳是刚更新的,就齐活了。
监控不用花哨:
→ 把 /var/log 所在分区的使用率,加进你已经在用的 Zabbix 或 Prometheus;
→ 设置告警阈值 85%,比等它爆满强十倍;
→ 顺手 grep "logrotate" /var/log/syslog | tail -10,每月扫一眼有没有 error 关键字。
今天下班前就能完成的具体操作
别收藏吃灰。现在就打开终端,按这五步走:
- 定位日志:执行
du -sh /var/log/* | sort -hr | head -5,找出前三大的日志目录; - 新建配置:运行
sudo vim /etc/logrotate.d/myweb; - 粘贴模板:把下面这段复制进去,把
/var/log/nginx/access.log换成你的真实路径,把www-data换成你服务的实际用户(比如nginx或apache2):/var/log/nginx/access.log { daily rotate 14 compress delaycompress dateext missingok notifempty create 0640 www-data www-data postrotate [ -f /run/nginx.pid ] && kill -USR1 $(cat /run/nginx.pid) endscript } - 立即测试:先
sudo logrotate -d /etc/logrotate.d/myweb看输出是否干净;再sudo logrotate -f /etc/logrotate.d/myweb,然后ls -lt /var/log/nginx/确认新归档出现; - 加进监控:打开你熟悉的 Zabbix 或 Prometheus 页面,找到“磁盘使用率”监控项,把
/var/log所在挂载点加进去,阈值设为 85%。
做完这五步,今晚睡觉前,你服务器的磁盘压力就少了一块大石头。