前置机跑得越久日志越多,不配轮转的结局都一样:磁盘被日志吃满,报送中断,半夜爬起来救火。日志轮转(logrotate)是Linux自带的日志管理机制,配置不难,难的是和应用日志的配合:轮转时应用要不要停、文件句柄怎么处理、压缩和保留的策略怎么定。这篇把logrotate的配置方法和报送场景的最佳实践讲全。
先讲一个最常见的坑:配了logrotate但没配对,轮转执行后应用还在往旧文件写(文件句柄没释放),新文件空着,磁盘照样涨——等于白配。这个坑的根源是不理解logrotate和应用写日志的机制差异,所以这篇先讲机制再讲配置,理解了原理,配置参数就都知道为什么那么填。
一、日志轮转的三要素
轮转配置要回答三个问题:多久转一次(频率)、转完的旧日志怎么办(压缩和保留)、轮转时应用怎么配合(通知机制)。
- 频率:按天转是最常见的节奏(日报类的应用日志,一天的量可控)。按大小转(比如单文件一百兆)适合日志量波动大的场景。报送类应用的日志量和工作日历强相关(月末量大),按天转加大小兜底(每天转,单文件超五百兆强制再转)的组合最稳。
- 保留和压缩:转出来的旧日志压缩存储(gzip,压缩比通常十比一,三天前的日志转压缩,近三天保留原样方便排查)、保留天数按合规要求(等保六个月的底线)和排查需求(实际排障很少翻一周前的日志)取平衡:在线保留三十天,压缩归档再存五个月,总够半年。
- 应用通知:轮转后应用必须重新打开日志文件(写新文件而不是继续写已被改名的旧文件)。通知的方式:postrotate脚本里发信号(kill -USR1 应用进程,应用收到信号重开日志)或复制截断模式(copytruncate,不改名直接截断,应用无感知)。
二、logrotate的配置文件详解
标准的配置文件结构(/etc/logrotate.d/目录下按应用建文件):
- 路径和通配:第一行指定日志文件的路径,通配符覆盖多个日志(/var/log/baosong/*.log转全部,也可以逐个列出)。多个应用日志分开建配置文件,各自的策略独立。
- 参数块:daily(每天转)、rotate 30(保留三十份)、compress(压缩)、delaycompress(延迟一天压缩,最近一份不压,方便翻看)、missingok(文件不存在不报错)、notifempty(空文件不转)。
- 脚本块:postrotate到endscript之间写轮转后的动作(发信号让应用重开日志),sharedscripts表示通配多个文件时脚本只执行一次(多发信号会打扰应用)。
一套报送应用的参考配置就十来行:daily、rotate 30、compress、delaycompress、copytruncate或postrotate信号、create属主权限。配置文件写完用logrotate -d(debug模式)验证语法和逻辑,确认无误再让它跑。
三、copytruncate和信号模式的选择
两种轮转模式的选择是配置的核心决策,各有适用场景。
- copytruncate(复制截断):机制是把当前日志复制一份作为轮转文件,然后把原文件清空,应用的文件句柄不变继续写。优点:应用零配合(不用发信号、不依赖应用实现信号处理),对不支持重开日志的应用是唯一选择。缺点:复制和截断之间有极小的窗口(这窗口里的日志可能丢失或错乱)——对日志完整性要求苛刻的场景是瑕疵。
- 信号模式(create加postrotate):机制是轮转时把旧文件改名,创建新文件,给应用发信号(USR1),应用收到后主动重开日志写新文件。优点:零丢失(改名不影响句柄,信号后新日志进新文件)。缺点:应用要实现信号处理(主流日志框架都支持:log4j、logback的RollingFileAppender其实自带轮转,和系统级配合时用它的外部模式)。
报送场景的建议:应用日志框架支持信号处理(Java系都支持)就用信号模式,追求零丢失;老旧应用或不确认的,copytruncate保平安。两种模式都配过的环境里,排查问题最多的不是模式本身,是配了信号模式但应用没真正处理信号,旧文件一直被写到巨大。验证方法:轮转后看新文件有没有内容增长,旧文件的大小是否停止变化。
四、和应用自身轮转的分工
Java应用普遍自带日志轮转(logback的滚动策略),系统级logrotate和应用级轮转会打架:应用自己转完,logrotate又来转一次,文件名错乱、重复压缩。分工的原则:一个日志文件只归一个轮转机制管。
- 应用管自己的:应用的滚动策略配按天加保留三十天,logrotate对该应用日志目录配置missingok加notifempty(空文件不动),实际不干预。这种方式最简单,适合标准Java应用。
- logrotate统一管:应用的滚动关掉(或滚动策略设成永不),日志一直追加单文件,logrotate负责一切。适合混合环境(多种语言的应用日志统一管理),运维口径单一。
报送前置机多是Java应用,推荐应用自己管:logback的配置十行以内,比系统级的配合少一层复杂度。logrotate管那些不会自己转的(系统日志、开源组件的日志)。
五、轮转的监控和兜底
轮转配置完不是结束,三个监控点保它长期有效。
- 轮转执行了没:logrotate有自己的执行日志(/var/lib/logrotate/logrotate.status),脚本执行失败(权限、语法)会静默。监控方案:cron任务的输出重定向到日志,定期检查status文件的更新时间,超过两天没更新就告警。
- 磁盘的持续观察:轮转正常但磁盘还在涨的病根很多:某个应用日志没被轮转覆盖到(新建的日志路径没进配置)、压缩失效(delaycompress的延迟积压)、保留数设太大。磁盘水位的监控(前面磁盘篇的三道线)配着轮转一起看。
- 半年度的演练复核:轮转配置改动后(新增应用、调整策略)做一次人工复核:手动触发一次轮转(logrotate -f 配置文件),看新文件生成、旧文件压缩、应用写入正常三件事都发生。三分钟的人工检查,防的是配置改错半年没人发现的哑雷。
搭贝在报送运维的实践里,日志轮转的配置核查是巡检的固定项:轮转是否覆盖全部日志路径、应用的重开机制是否验证过、保留周期是否合规,三项用运维台账登记,巡检时逐项核对。轮转这种配完就忘的基础设施,恰恰需要这种清单化的定期关照。
常见问题
Q:轮转后新日志文件是空的怎么回事?
九成是应用还在写旧文件:copytruncate模式下检查截断是否生效(旧文件大小是否归零)、信号模式下检查应用是否处理了信号(看旧文件是否还在增长)。验证的快速方法:tail -f 新文件,触发一条应用日志(发个测试请求),新文件没动静就是应用没切换。处理:应用侧修信号处理,或暂时改用copytruncate。
Q:日志压缩后发现要查问题怎么办?
zgrep、zcat直接查压缩文件(zgrep 关键词 *.gz),不用解压。频繁要查的时段(最近一周),用delaycompress延长不压缩的窗口(延迟七天再压)。归档更久的日志要回查,先解压到临时目录再分析,别在生产日志目录里解压(磁盘空间的风险)。
Q:磁盘还是满但轮转正常?
按顺序查三处:轮转覆盖外的日志(find全盘的大日志文件,常有漏网——应用升级后换了日志路径,配置没跟上)、coredump和临时文件(应用崩溃的core文件动辄几个G)、日志之外的增长(数据库、备份残留)。轮转只管它配置内的文件,磁盘治理要全盘视角(前面磁盘专篇的思路)。
Q:Windows前置机怎么做日志轮转?
Windows没有logrotate,方案三个:应用自管(logback滚动,推荐)、PowerShell脚本加计划任务(自写脚本实现复制截断,逻辑参考copytruncate)、第三方工具(日志轮转的开源Windows版)。Windows的报送前置机建议应用自管:跨平台的日志框架都支持,策略和行为和Linux侧一致,运维口径统一。
Q:多台前置机的轮转策略怎么保持一致?
配置文件进版本库(Git管理logrotate和应用日志配置),变更走评审,批量下发用自动化工具(Ansible的模板分发)。配置漂移是多机环境的慢性病:某台手动改过参数,半年后行为不一致排查到怀疑人生。搭贝的运维台账登记每台的配置版本,巡检核对,漂移无所遁形。