4、logrotate日志轮转:日志轮转原理、logrotate配置语法、车载存储空间管理策略
4.1 为什么车载系统离不开日志轮转?
说实话,我刚入行做车载Linux那会儿,踩过一个很蠢的坑。当时一个IVI(车载信息娱乐系统)项目,跑了大概两周,突然系统响应变得特别慢。我一查,好家伙,/var/log目录下有个日志文件撑到了2.3GB。你想想看,车载嵌入式设备的存储空间本来就金贵,一个日志文件就把emmc吃掉一大块,这谁受得了?
从那以后,我养成了一个习惯——任何上车的系统,第一件事就是配好logrotate。说白了,日志轮转就是让日志文件“自动瘦身”的机制。它不会让你的日志无限增长,而是按照你设定的规则,定期把旧日志压缩、归档、甚至删除。
车载环境尤其特殊。存储空间有限,而且往往是emmc或者NAND Flash,写入寿命有限。如果日志一直疯狂写,不仅空间会爆,Flash的寿命也会被快速消耗。嗯,这里要注意,logrotate不是万能的,但它绝对是第一道防线。
4.2 logrotate轮转原理:其实没那么玄乎
logrotate的工作原理,我用一句话就能说清楚:它是个定时任务,到了时间就把当前日志文件“挪走”,然后让应用程序重新生成一个新的空日志文件。
具体流程是这样的:
- 系统定时器(通常是cron或者systemd timer)触发logrotate
- logrotate读取配置文件,检查哪些日志文件需要轮转
- 如果满足条件(比如文件大小超了,或者时间到了),就把当前日志重命名
- 通知应用程序关闭旧文件句柄,打开新文件
- 对旧日志进行压缩、删除等后续处理
这里有个关键点——通知机制。我记得有个项目,logrotate配置好了,但日志就是不轮转。查了半天,发现是应用程序没有正确处理SIGHUP信号。logrotate轮转完文件后,会发一个SIGHUP给应用程序,应用程序收到信号后应该重新打开日志文件。如果应用程序不处理这个信号,那日志就会继续往旧文件里写,轮转就白做了。
核心要点:logrotate本身不写日志,它只是管理日志文件。真正的日志写入者是应用程序。所以轮转后,必须确保应用程序能重新打开日志文件。
4.3 logrotate配置语法:我常用的几个模板
logrotate的配置文件通常放在/etc/logrotate.conf和/etc/logrotate.d/目录下。我个人习惯把每个应用的配置单独放在/etc/logrotate.d/里,这样管理起来清晰。
先看一个最基础的配置:
/var/log/syslog {
weekly
rotate 4
compress
delaycompress
missingok
notifempty
postrotate
/usr/bin/killall -HUP syslogd
endscript
}
这个配置什么意思?我拆开讲:
weekly:每周轮转一次。你也可以用daily、monthly,甚至size 100M按大小轮转rotate 4:保留4个旧日志文件。超过4个,最老的那个会被删除compress:旧日志用gzip压缩。车载空间紧张,我建议一定要开delaycompress:延迟压缩。意思是这次轮转出来的旧日志先不压缩,等下次轮转再压缩。为什么?因为有些应用还在写旧日志,延迟压缩可以避免数据丢失missingok:日志文件不存在也没关系,不报错notifempty:日志文件为空就不轮转postrotate/endscript:轮转完成后执行的脚本,这里就是通知syslogd重新打开日志
车载场景下,我推荐一个更实用的配置:
/var/log/ivi_app.log {
size 50M
rotate 3
compress
delaycompress
missingok
notifempty
dateext
dateformat -%Y%m%d-%s
sharedscripts
postrotate
/usr/bin/killall -USR1 ivi_app
endscript
}
这里有几个车载专用的技巧:
size 50M:按大小轮转,而不是按时间。车载日志量波动大,按大小更靠谱rotate 3:只保留3个旧文件。车载存储有限,别贪多dateext:用日期命名旧文件,方便排查问题sharedscripts:如果匹配多个日志文件,脚本只执行一次
我的经验:车载系统里,我一般把日志总大小控制在200MB以内。比如每个日志文件50MB,保留3个旧文件,再加上当前文件,总共也就200MB。这个量级对于大多数车载设备来说是可以接受的。
4.4 车载存储空间管理策略:实战中的取舍
车载存储管理,说白了就是一场“空间与信息”的博弈。你想保留更多日志方便排查问题,但存储空间就那么点。我经历过一个项目,客户要求保留30天的日志,但emmc只有4GB。你算算,系统本身占掉2GB,应用数据占1GB,留给日志的只有1GB。30天,每天33MB,这怎么可能?
所以,我总结了一套车载存储管理的策略:
| 策略 | 说明 | 适用场景 |
|---|---|---|
| 按大小轮转 | 设置单个日志文件上限,比如50MB | 日志量波动大的场景 |
| 限制总大小 | 通过rotate数量控制总日志量 | 存储空间固定的嵌入式设备 |
| 分级存储 | 关键日志保留更久,普通日志快速清理 | 需要区分日志重要性的场景 |
| 压缩归档 | 旧日志用gzip压缩,压缩比通常5:1 | 所有车载设备都建议开启 |
| 远程上传 | 重要日志上传到云端,本地只保留最近几份 | 有网络连接的车载系统 |
我曾经在一个T-Box项目里用过“分级存储”策略。系统日志只保留3天,但CAN总线日志保留7天,故障快照保留30天。怎么实现的?很简单,不同的日志写到不同的目录,分别配置logrotate规则:
/var/log/system/*.log {
size 10M
rotate 2
compress
}
/var/log/canbus/*.log {
size 20M
rotate 5
compress
}
/var/log/crash/*.log {
size 5M
rotate 10
compress
# 故障快照不自动删除,由专门脚本管理
}
警告:千万不要把所有日志都塞到同一个目录下用同一个规则。车载系统里,不同模块的日志重要性和量级完全不同。混在一起管理,要么重要日志被过早清理,要么空间被不重要日志占满。
4.5 避坑指南:我踩过的那些坑
做车载logrotate配置这么多年,我踩过的坑真不少。挑几个典型的说说:
坑一:轮转后应用不写日志了
我曾经遇到一个情况,logrotate配置好了,轮转也正常执行,但应用就是不写新日志。查了半天,发现是copytruncate参数的问题。这个参数的意思是“先复制再截断”,不通知应用。但有些应用对文件截断处理不好,会导致日志丢失。我的建议是:能用create方案就别用copytruncate。
坑二:轮转频率太高把Flash写坏了
emmc和NAND Flash都有写入寿命。如果设置daily轮转,每次轮转都要压缩、写入新文件,对Flash的磨损不小。我建议车载系统里,非关键日志用weekly或者size触发,别让日志轮转变成Flash杀手。
坑三:忘记测试轮转后的恢复场景
我记得有一次,客户反馈说车机死机重启后,日志文件全丢了。我一查,原来是logrotate配置了create,但重启后日志目录权限变了,应用没有权限创建新日志文件。从那以后,我每次配置完logrotate,都会做一次“断电重启测试”,确保日志系统在异常场景下也能正常工作。
4.6 总结一下
logrotate这东西,配置起来不难,但要想在车载环境里用好,还是得花点心思。核心就三点:
- 按需配置:不同模块不同策略,别一刀切
- 控制总量:车载存储有限,总日志量必须设上限
- 测试验证:配置完一定要做压力测试和异常场景测试
嗯,如果你现在去配logrotate,我建议先从size 50M和rotate 3开始,配合compress和dateext。这个组合在大多数车载场景下都不会出大问题。等跑一段时间,再根据实际日志量调整参数。
下一章,我们会聊聊日志分析工具和故障诊断方法。到时候我会分享一些我实际用过的调试技巧,保证比你看文档来得实在。