Logrotate 日志轮转实战:核心指令、应用配置与排错指南

日志文件不轮转,磁盘迟早被写满。本文详解 Linux logrotate 的工作原理、配置文件结构、rotate/compress/copytruncate 等核心指令、自定义应用轮转配置的写法与 debug 排错方法,并说明本地轮转与观测云平台留存如何分工。

最佳实践
Logrotate 日志轮转实战:核心指令、应用配置与排错指南技术指南封面

日志轮转(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 最省心。

排错:轮转没生效怎么办?

  1. 查状态文件:sudo cat /var/lib/logrotate/status,确认目标文件在轮转清单中及上次轮转时间;
  2. 干跑调试:sudo logrotate -d /etc/logrotate.d/myapp,只模拟不执行,配置拼写错误(如 compresss)会直接报 公开资料未说明 option;
  3. 强制执行:sudo logrotate -fv /etc/logrotate.conf,-f 立即轮转、-v 输出详细过程。

若 prerotate/postrotate 脚本不执行,检查脚本是否有可执行权限(chmod +x)、路径是否正确。

本地轮转与平台留存如何分工?

在轮转前后分别写入带唯一标识的测试日志,再到集中日志系统中查找,检查是否漏采、重复或仍只读取旧文件。使用观测云时,可按 DataKit 文件日志采集配置核对路径匹配与采集状态。

平台中已经收到的数据不依赖本地副本,但尚未读取或尚未发送的数据仍可能随清理丢失。缩短本地保留时间前,应同时测试采集器重启、发送中断及恢复后的续读。

总结

logrotate 的配置可以浓缩为一句话:定好触发条件(时间或大小)、定好保留份数、处理好"应用重开文件"这个坑。集中存储不能代替轮转测试,尤其要检查清理发生时是否仍有未采集的数据。

常见问题(FAQ)

Q:轮转后应用不再写日志了,是什么原因?
最常见的原因是应用仍持有旧文件句柄:旧文件被改名后,应用的输出跟着旧文件走了。解决方案二选一:配置 postrotate 脚本通知应用重开日志文件,或改用 copytruncate 模式。

Q:logrotate 是实时守护进程吗?
不是。logrotate 由系统定时任务(cron.daily 或 systemd timer)按天触发,所以 size 条件的最小检查粒度也是一天;需要更高频控制时,可以自建 cron 条目指定单独的配置文件和状态文件。

Q:如何保留更久的历史日志但又不占磁盘?
将历史日志发送到独立的集中存储,并分别设置本地缓冲窗口和远端保留期限。删除本地文件前,应验证数据已送达,以及历史记录能否按需要检索或恢复。

Q:rotate 0 是什么意思?
表示不保留任何历史副本——轮转时直接删除旧文件。适合日志已实时上报平台、本地完全不留档的场景。


系列阅读:Linux 系统日志管理入门 | 降低日志成本七步法

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台