为什么需要日志轮转
你有没有遇到过服务器突然卡死,登录一看,/var/log 目录占满了整个磁盘?这种情况十有八九是某个服务疯狂写日志,比如 Nginx 或 Tomcat,几天下来生成几个 GB 的日志文件。这时候才想起来该做日志轮转,其实已经晚了。
日志轮转的核心目的就两个:控制单个日志文件大小,防止无限增长;自动归档旧日志,保留合理周期。
使用 logrotate 管理系统日志
Linux 上最常用的工具就是 logrotate。它默认每天由 cron 自动执行一次,检查配置并处理符合条件的日志文件。
比如你想对 Nginx 的访问日志做轮转,可以创建配置文件 /etc/logrotate.d/nginx:
/var/log/nginx/*.log {
daily
missingok
rotate 7
compress
delaycompress
notifempty
create 0644 www-data www-data
sharedscripts
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 `cat /var/run/nginx.pid`
fi
endscript
}
这段配置的意思是:每天轮转一次,保留最近 7 份日志,压缩旧文件,如果日志为空就不处理,新文件权限设为 0644 并归属 www-data 用户。最关键的是 postrotate 里的命令,通知 Nginx 重新打开日志文件,否则它还会往旧文件里写。
按大小触发轮转
有些场景下日志量波动大,按天轮转不合适。比如一个高并发 API 服务,可能几小时就产出上百 MB 日志。这时候可以用 size 条件替换 daily:
size 100M
这样当日志文件达到 100MB 就立即触发轮转,不依赖时间。
应用自己的程序怎么加轮转
如果你在用 Python 写后台脚本,或者 Go 编译的服务,可以直接在代码里集成轮转逻辑。以 Python 的 logging 模块为例:
import logging
from logging.handlers import RotatingFileHandler
handler = RotatingFileHandler('app.log', maxBytes=10*1024*1024, backupCount=5)
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger = logging.getLogger(__name__)
logger.addHandler(handler)
logger.setLevel(logging.INFO)
这里设置了单个日志最大 10MB,最多保留 5 个历史文件。当 app.log 写满后,自动重命名为 app.log.1,再新建 app.log 继续写。
别忘了验证和调试
配置写完别直接扔生产环境。用下面这条命令手动跑一遍,看有没有报错:
logrotate -d /etc/logrotate.d/nginx
-d 是 debug 模式,不会真正执行,但会输出详细过程。确认没问题后再用 -f 强制执行一次测试:
logrotate -f /etc/logrotate.d/nginx
看看日志文件是不是按预期分割了,权限对不对,服务有没有正常收到信号。