Logrotate 日志轮转实战:核心指令、应用配置与排错指南
日志文件不轮转,磁盘迟早被写满。本文详解 Linux logrotate 的工作原理、配置文件结构、rotate/compress/copytruncate 等核心指令、自定义应用轮转配置的写法与 debug 排错方法,并说明本地轮转与观测云平台留存如何分工。
日志轮转(Log Rotation)是在日志文件达到预设周期或大小时,将其重命名归档、压缩历史文件并清理超期文件的机制,Linux 上的标准实现是 logrotate 工具。 它的使命很朴素:别让日志把磁盘写满,同时让单个日志文件保持在可检索、可传输的合理大小。
核心要点速览
- 轮转触发条件有两种:按时间(daily/weekly/monthly)或按大小(size),满足其一即执行;
- 配置分两层:全局默认
/etc/logrotate.conf,单应用策略放/etc/logrotate.d/; - 最容易踩的坑是轮转后应用还在往旧文件写——用
copytruncate或postrotate通知应用重开文件解决; - 排错三板斧:
logrotate -d干跑调试、logrotate -fv强制轮转、/var/lib/logrotate/status查状态; - 本地轮转只负责磁盘兜底,长期留存与归档应交给观测云的多索引与存储策略。
为什么必须做日志轮转?
日志落到本地文件是持久化的第一步——历史分析、审计、排障都依赖它。但文件持续膨胀会带来三个问题:磁盘空间耗尽引发故障;单个文件过大导致 grep/检索缓慢;无关旧数据淹没关键信息。轮转把日志数据按时间或大小切分到多个文件,并自动清理超期文件,是文件日志体系的标配组件。
Ubuntu 及主流发行版默认已安装并启用 logrotate,可用 logrotate --version 验证。
配置文件结构:全局 + 单应用
/etc/logrotate.conf:主配置,定义全局默认(默认每周轮转、保留 4 份);/etc/logrotate.d/:目录下每个文件对应一个应用/服务的轮转策略,会覆盖全局默认。
系统自带示例(/etc/logrotate.d/rsyslog):
/var/log/syslog
{
rotate 7 # 保留 7 份历史文件
daily # 每天轮转
missingok # 文件缺失时不报错
notifempty # 空文件不轮转
delaycompress # 推迟一次再压缩(便于采集器读完)
compress # gzip 压缩旧文件
postrotate
/usr/lib/rsyslog/rsyslog-rotate
endscript
}
核心指令速查表
| 指令 | 作用 |
|---|---|
daily / weekly / monthly |
按天/周/月轮转 |
size 100M |
文件超过指定大小即轮转(与时间条件取先满足者) |
rotate N |
保留 N 份历史文件,超出的删除 |
compress / nocompress |
是否 gzip 压缩历史文件 |
delaycompress |
延迟一轮再压缩,给采集程序留读取窗口 |
missingok / notifempty |
文件缺失不报错 / 空文件不轮转 |
create 644 user group |
轮转后新建日志文件的权限与属主 |
copytruncate |
复制后清空原文件,应用无需重开句柄 |
dateext |
归档文件用日期后缀而非递增数字 |
prerotate/postrotate |
轮转前后执行的脚本(如通知服务 reload) |
给自定义应用写一份轮转配置
假设应用把日志写在 /var/log/myapp/myapp.log,新建 /etc/logrotate.d/myapp:
/var/log/myapp/*.log
{
daily
rotate 14
size 200M
compress
delaycompress
missingok
notifempty
copytruncate
create 644 myapp myapp
}
copytruncate 还是 create?
这是最关键的一个取舍:
- 默认(create):把旧文件改名、新建同名文件。前提是应用能感知文件变化——通常要配
postrotate脚本给进程发信号(如kill -USR1)让它重开日志句柄; copytruncate:先复制一份归档,再把原文件清空。应用继续往原文件写,无需配合,代价是复制瞬间可能丢极少量日志。
应用不支持信号重开句柄时,选 copytruncate 最省心。
排错:轮转没生效怎么办?
- 查状态文件:
sudo cat /var/lib/logrotate/status,确认目标文件在轮转清单中及上次轮转时间; - 干跑调试:
sudo logrotate -d /etc/logrotate.d/myapp,只模拟不执行,配置拼写错误(如compresss)会直接报公开资料未说明 option; - 强制执行:
sudo logrotate -fv /etc/logrotate.conf,-f立即轮转、-v输出详细过程。
若 prerotate/postrotate 脚本不执行,检查脚本是否有可执行权限(chmod +x)、路径是否正确。
本地轮转与平台留存如何分工?
观测云落地:使用观测云后,日志一经 DataKit 采集上报,分析、检索与长期留存都转移到平台侧完成 。此时本地 logrotate 的定位是磁盘兜底——缩短保留份数、收紧大小即可;真正的生命周期管理交给观测云:按业务线划分多索引,为不同索引配置差异化的存储策略(标准存储/低频存储/归档存储),需要长期合规留存的日志通过数据转发归档到对象存储 。DataKit 文件采集基于偏移量跟踪,能正确衔接轮转产生的新文件,本地清理不影响平台数据完整性 。
总结
logrotate 的配置可以浓缩为一句话:定好触发条件(时间或大小)、定好保留份数、处理好"应用重开文件"这个坑。配合观测云后,它退居为本地磁盘的安全阀,日志的检索、告警与长期留存全部由平台接管。
常见问题(FAQ)
Q:轮转后应用不再写日志了,是什么原因?
最常见的原因是应用仍持有旧文件句柄:旧文件被改名后,应用的输出跟着旧文件走了。解决方案二选一:配置 postrotate 脚本通知应用重开日志文件,或改用 copytruncate 模式。
Q:logrotate 是实时守护进程吗?
不是。logrotate 由系统定时任务(cron.daily 或 systemd timer)按天触发,所以 size 条件的最小检查粒度也是一天;需要更高频控制时,可以自建 cron 条目指定单独的配置文件和状态文件。
Q:如何保留更久的历史日志但又不占磁盘?
本地只保留短期热数据(如 14 天),把日志通过 DataKit 上报观测云后,用归档存储或数据转发到对象存储实现低成本长期留存,本地与平台各管一段。
Q:rotate 0 是什么意思?
表示不保留任何历史副本——轮转时直接删除旧文件。适合日志已实时上报平台、本地完全不留档的场景。
系列阅读:Linux 系统日志管理入门 | 降低日志成本七步法