Linux logrotate 命令详解:自动化日志管理的核心技术

在 Linux 服务器管理中,日志文件是诊断问题、监控系统状态和安全审计的生命线。随着服务持续运行,日志文件会不断增长,可能导致磁盘空间耗尽、检索效率低下等问题。logrotate 是 Linux 系统内置的强大工具,专门用于自动化管理日志文件。它能根据设定的规则,定期轮替(rotate)、压缩、删除日志文件,并可选地通知服务重新打开日志文件。本指南将深入探讨其工作原理、配置方法、最佳实践和常见示例。

目录#

  1. logrotate 是什么?为什么需要它?
  2. 核心工作原理
  3. 配置文件详解
    • 3.1 主配置文件 (/etc/logrotate.conf)
    • 3.2 自定义配置文件 (/etc/logrotate.d/)
    • 3.3 配置指令详解
  4. 常用配置选项与实践
  5. 最佳实践
  6. 示例配置详解
    • 6.1 标准系统日志 (syslog)
    • 6.2 Nginx Web 服务器日志
    • 6.3 自定义应用程序日志
    • 6.4 处理没有 PID 文件的守护进程
  7. logrotate 命令详解
    • 7.1 手动运行 logrotate
    • 7.2 调试与验证
  8. 故障排除
  9. 总结
  10. 参考资源

1. logrotate 是什么?为什么需要它?#

logrotate 是一个旨在简化日志文件管理系统的命令行工具和守护进程。其主要功能包括:

  • 轮替 (Rotate): 重命名现有日志文件(例如 app.log 变成 app.log.1),为新的日志文件腾出位置。
  • 压缩: 压缩旧的日志文件以节省磁盘空间(通常使用 gzip)。
  • 删除: 根据设定的规则(如保留天数、保留文件数)删除过旧的日志文件。
  • 邮件通知: (可选)在删除文件前将日志文件通过邮件发送。
  • 创建新文件: 在轮替后创建新的、空的日志文件。
  • 服务通知: (可选)在轮替后通知相关服务重新加载或重新打开其日志文件(确保服务继续写入新文件)。

为什么需要使用 logrotate?

  • 防止磁盘空间耗尽: 未经管理的日志会无限增长。
  • 提高可维护性: 避免单个日志文件过大,难以打开、搜索或传输。
  • 组织归档: 按时间或序列号组织历史日志,方便回溯分析。
  • 符合审计要求: 帮助满足需要保留特定时间段日志的合规要求。
  • 自动化管理: 依赖系统的 cron 任务定时执行,无需人工干预。

2. 核心工作原理#

logrotate 本身是一个由 /etc/cron.daily/logrotate(或类似路径,取决于发行版)触发的日计划任务(cron job)。其内部工作流程大致如下:

  1. 读取配置: 加载主配置文件 /etc/logrotate.conf/etc/logrotate.d/ 目录下的所有自定义配置文件。
  2. 检查轮替条件: 对于配置中定义的每个日志文件或日志组:
    • 检查是否满足轮替条件(通常是基于时间间隔:每天、每周、每月;或者基于文件大小)。
    • 检查ifempty选项(是否轮替空文件)。
  3. 执行轮替操作:
    • 重命名: 将当前日志文件重命名(例如 logfile -> logfile.1)。之前轮替生成的文件(logfile.1, logfile.2.gz...)也会被重命名,通常 logfile.1 -> logfile.2.gz)。
    • (可选)压缩: 根据 compressdelaycompress 选项,立即压缩或延迟压缩旧文件(logfile.1 -> logfile.2.gz)。
    • (可选)邮件: 如果配置了 mailmailfirst/maillast,将指定文件发出邮件。
    • (可选)删除: 根据 maxage, maxsize, 或 rotate count 选项删除过旧的归档文件。
  4. 创建新日志文件:
    • 在原始位置创建一个新的、空的日志文件。
    • 根据 create mode owner group 选项设置新文件的权限和所有权。
    • 如果使用了 copytruncate 选项,会复制当前日志文件后将其截断(适用于不支持重载的应用程序)。
  5. (可选)通知服务:
    • 如果配置了 sharedscriptspostrotate/endscript 块(或 prerotate),并且使用的是 sharedscripts,则在处理完同一配置文件内定义的所有日志文件后,执行一次指定的命令(通常是让服务重新加载配置或重新打开日志文件的信号,如 kill -HUP)。
    • 对于 copytruncate,通知步骤通常省略(因为原始文件被保留)。
  6. 日志记录(可选): logrotate 自身的状态信息(成功、失败、错误)会记录到 /var/lib/logrotate/status/var/lib/logrotate/logrotate.status

3. 配置文件详解#

3.1 主配置文件 (/etc/logrotate.conf)#

  • 存放全局默认设置。
  • 包含指令如 weekly, rotate 4, compress, create, include /etc/logrotate.d
  • 通常不需要频繁修改,自定义配置建议放在 /etc/logrotate.d/ 目录下。

3.2 自定义配置文件 (/etc/logrotate.d/)#

  • 存放针对特定服务或应用程序的配置片段。
  • 文件命名没有严格要求(通常与服务同名,如 nginx, syslog, myapp),但推荐使用有意义的名字。
  • 系统安装的服务包(如 nginx, apache, syslogd)通常会自动在此目录生成配置文件。
  • 管理员在此目录添加自定义服务的配置。
  • 该目录会被 /etc/logrotate.conf 中的 include 指令包含。

3.3 配置指令详解#

以下是一些最常用和关键的配置指令:

  • 指定日志文件:

    • /var/log/myapp/*.log: 匹配 /var/log/myapp/ 目录下所有 .log 结尾的文件。
    • /var/log/nginx/access.log /var/log/nginx/error.log: 明确列出多个日志文件路径。
    • "/var/log/special name.log": 使用引号包裹包含空格的文件名。
  • 轮替频率 (指定一个即可):

    • daily: 每天轮替。
    • weekly: 每周轮替(通常周日)。
    • monthly: 每月轮替(每月第一天)。
    • size [SIZE]: 当文件大小超过指定 SIZE 时轮替(如 size 100M, size 1G)。这是基于大小的轮替,会忽略时间设置。
    • [maxsize](https://stackoverflow.com) [SIZE]: 在下一个daily/weekly/monthly调度周期内,如果文件大小超过指定 SIZE,也会立即轮替。常用于快速增长的日志。
  • 保留策略:

    • rotate [COUNT]: 保留 COUNT 个旧的日志文件(轮替后的文件)。如果设为 0,则不保留任何旧文件(轮替后直接删除)。这是最常用的计数保留策略。
    • maxage [DAYS]: 删除超过指定天数(根据文件修改时间)的归档日志文件。通常比 rotate 更精确控制保留时间。
    • maxsize [SIZE] (for deletion): 如果一个归档文件(如 *.gz)的大小超过 SIZE,则将其删除(即使在 rotate 设定的计数范围内)。此处的 maxsize 指令与轮触发器的不同,用于删除。
    • ifempty: 即使日志文件为空也进行轮替(默认行为)。
    • notifempty: 如果日志文件为空,则不轮替。
  • 日志文件压缩与归档:

    • compress: 在轮替后立即使用 gzip 压缩旧文件(文件扩展名后加 .gz)。
    • nocompress: 不压缩旧文件(默认)。
    • delaycompress: 将最近一次轮替生成的文件延迟到下一次轮替时压缩。适用于需要查看最近一个未压缩日志的场景。常与 compress 一起使用。
    • compressext [.EXT]: 指定压缩后的扩展名(如 .zip,但通常依赖 compresscmd)。
    • compressoptions [OPTIONS]: 传递自定义参数给压缩命令(如 -9gzip)。
    • compresscmd [COMMAND]: 指定替代 gzip 的压缩命令(如 bzip2, xz)。
    • dateext: 使用日期(YYYYMMDD,或 dateformat 指定格式)代替序列号作为旧文件的后缀(如 logfile-20240115)。与 rotate 结合时删除逻辑不变。
    • dateformat [FORMAT]: 配合 dateext 使用,自定义日期格式(如 %Y%m%d-%s 包含时间戳)。
  • 新日志文件创建:

    • create: 在轮替后立即创建一个新的空白日志文件(默认行为)。
    • nocreate: 轮替后不创建新文件(让应用程序自己创建)。
    • create mode owner group: 创建新文件时指定权限、所有者、所属组(如 create 0640 www-data adm)。强烈推荐为服务正确配置此选项,确保应用进程有写入权限。
  • 服务通知与重载:

    • postrotate ... endscript: 在轮替完该配置块中的所有日志文件(且在所有新文件创建之后),执行指定命令或脚本。命令写在 postrotateendscript 之间。常用命令是 kill -HUP $service_pid/usr/sbin/service nginx reload
    • prerotate ... endscript: 在轮替日志文件之前执行指定命令。
    • sharedscripts: 默认情况下,postrotate/prerotate 脚本针对每个轮替的文件执行一次。如果配置了 sharedscripts,则无论该配置块中有多少个日志文件被轮替,脚本都只执行一次最佳实践通常启用 sharedscripts
    • su owner group: 在轮替操作和脚本执行时,切换到指定的 ownergroup。常用于容器或非 root 用户的日志文件(如 su www-data adm)。解决文件权限问题(特别是 SELinux 上下文)。
  • 特殊处理选项:

    • copytruncate: 复制当前日志文件到一个备份文件(类似 cp logfile logfile.old),然后将原始文件截断为0字节大小。适用于无法通过信号通知重新打开文件(或重载)的、持续写入文件的应用程序。这是处理“不支持重载”应用的最后手段,存在日志丢失风险(在cptruncate之间写入的数据)。
    • mail address: 删除旧文件时,将指定文件(由mailfirst/maillast决定)发送邮件到指定地址。
    • mailfirst: 当轮替计数已满时,删除最旧的归档文件前,将其邮寄出去(需配合 mail)。
    • maillast: (默认) 当轮替计数已满时,删除最的归档文件前,将其邮寄出去(需配合 mail)。
    • nomail: 不邮寄旧日志文件。
  • 脚本扩展:

    • include or include file: 在当前位置包含另一个配置文件的内容。

4. 常用配置选项与实践#

  • 基础模板: 多数配置包含 rotate, compress, create, delaycompress, postrotate, sharedscripts
  • 时间 vs 大小: 优先使用 weekly/monthly 结合 rotate 进行常规归档;对于快速增长的关键日志,添加 sizemaxsize 确保及时轮替。
  • 保留策略: rotate 52 结合 weekly 提供一年的历史记录;maxage 180 确保删除超过 6 个月的旧文件。两者可结合使用(maxage 优先)。
  • 安全与权限: 必须使用 create mode owner groupsu owner group 确保轮替后创建的新文件能被服务写入(尤其是 SELinux 环境下)。
  • sharedscripts: 几乎总是启用以避免不必要的脚本执行。
  • copytruncate: 尽量避免使用,仅在应用程序绝对不支持重载信号(HUP, USR1, USR2)时才启用。记住其潜在风险。
  • dateext: 便于按日期查找归档日志。
  • nomail: 生产环境通常不需要邮件功能。

5. 最佳实践#

  1. 使用 /etc/logrotate.d/: 将自定义服务配置放在独立的 /etc/logrotate.d/myapp 文件中,保持主配置文件干净。
  2. 设置正确的所有权(createsu): 这是最常见的权限错误来源。确保新创建的文件可被服务写入。
  3. 启用 compressdelaycompress: 节省空间,同时保留最近一个未压缩日志方便查看。
  4. 明确 rotatemaxage: 不要依赖默认保留策略。根据存储空间和合规要求精确设定。
  5. 谨慎使用 copytruncate: 只在别无选择时使用,并理解风险。
  6. 启用 sharedscripts: 提高效率。
  7. 考虑容器环境: 对于容器日志(挂载到主机路径 /var/lib/docker/containers/*/*.log),使用 su root root(或 su 指定容器内用户)并结合 create 权限可能需要特别注意。/run/logrotate 机制也是解决方法之一。
  8. 测试配置更改: 使用 logrotate -d -f /etc/logrotate.d/myapp 模拟运行 (-d 调试模式) 并强制执行 (-f)。测试后再应用到生产环境!
  9. 监控状态文件: 检查 /var/lib/logrotate/status 了解上次轮替时间和轮替结果。
  10. 处理空文件: 除非特殊需求,使用默认的 ifempty。如果确定需要忽略空文件,使用 notifempty
  11. SELinux: 配置后如果出现权限问题(通常create后新文件服务无法写入),检查 SELinux 审计日志 (/var/log/audit/audit.log),可能需要调整上下文 (chcon -t type_t newlogfile) 或制定策略 (semanage fcontext, restorecon)。su 指令有时能更好地继承上下文。
  12. 处理不写入 PID 文件的应用: 如果 postrotate 脚本需要向进程发信号 (kill -HUP),但应用进程没有 PID 文件:
    • 最佳: 让应用支持通过参数写入 PID 文件。
    • 次选:postrotate 脚本中用 pidofpgrep 查找 PID(需小心应用唯一性)。例如: /usr/bin/pkill -HUP -x 'processname'
    • 最后: 考虑 copytruncate(有风险)。

6. 示例配置详解#

6.1 标准系统日志 (syslog)#

/var/log/syslog
{
    rotate 7                 # 保留过去7次轮替的文件
    daily                    # 每天轮替一次
    missingok                # 如果日志文件丢失,不报错
    notifempty               # 空文件不轮替
    delaycompress            # 延迟压缩最近一次轮替的文件
    compress                 # 压缩更旧的文件
    postrotate               # 轮替后需要通知 rsyslog
        /usr/lib/rsyslog/rsyslog-rotate
    endscript
    su syslog adm            # 以 syslog 用户和 adm 组身份操作(解决 Debian/Ubuntu 上权限问题)
}
 
/var/log/mail.info
/var/log/mail.warn
/var/log/mail.err
/var/log/mail.log
{
    rotate 7
    daily
    missingok
    notifempty
    delaycompress
    compress
    su syslog adm
}

6.2 Nginx Web 服务器日志#

/var/log/nginx/*.log {      # 处理 NGINX 所有日志文件
    daily                    # 每天轮替
    missingok                # 如果日志文件丢失,不报错
    rotate 60                # 保留60个归档文件(60天历史)
    compress                 # 压缩旧日志
    delaycompress            # 延迟压缩最新一轮的归档
    notifempty               # 不轮替空文件
    create 0640 www-data adm # 创建新文件,设置权限为640,所有者为 www-data, 组为 adm
    sharedscripts            # 所有日志文件轮替完后只执行一次脚本
    postrotate
        # 向 nginx master 进程发送 USR1 信号使其重新打开日志文件
        kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true # 安全地发信号
    endscript
    su www-data adm          # 使用 www-data 用户和 adm 组运行(确保权限继承)
}

6.3 自定义应用程序日志 (/etc/logrotate.d/myapp)#

假设应用日志在 /opt/myapp/logs/app.log,应用启动时写入 PID 文件 /run/myapp.pid

/opt/myapp/logs/app.log {
    weekly                   # 每周轮替一次
    maxsize 200M             # 或者文件大于200M立即轮替
    rotate 8                 # 保留8个归档文件
    compress                 # 压缩旧日志
    delaycompress            # 延迟压缩最近一轮
    missingok
    notifempty
    create 0640 appuser appgroup # 确保应用用户能写入新文件
    sharedscripts
    postrotate
        # 向应用发送 HUP 信号使其重新打开日志文件 (假设进程支持 HUP)
        kill -HUP `cat /run/myapp.pid 2> /dev/null` 2> /dev/null || true
    endscript
    su appuser appgroup      # 推荐:使用应用程序用户权限操作
}

6.4 处理没有 PID 文件的守护进程(使用 pkill#

/var/log/daemon-no-pid.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 0640 root root
    sharedscripts
    postrotate
        # 假设守护进程名是 'unique-daemon-name', 使用 -HUP 信号
        pkill -HUP -x unique-daemon-name || true  # '-x' 确保精确匹配命令名
    endscript
    # 可能需要 su 指定用户(如果守护进程以非 root 运行且文件权限有要求)
    # su daemonuser daemongroup
}

7. logrotate 命令详解#

命令通常由 cron 自动调用。管理员也可手动运行:

# 强制立即运行 logrotate(处理所有日志)
logrotate -f /etc/logrotate.conf
 
# 强制轮替特定配置文件(/etc/logrotate.d/myapp)
logrotate -f /etc/logrotate.d/myapp
 
# 模拟运行(DEBUG模式)- “假跑”, 不会真正修改文件,输出详细执行计划
logrotate -d /etc/logrotate.d/myapp
 
# 查看状态文件(记录上次轮替时间等信息)
cat /var/lib/logrotate/logrotate.status
 
# 模拟 + 强制运行特定配置
logrotate -d -f /etc/logrotate.d/nginx

8. 故障排除#

  • 日志文件没轮替:
    • 检查配置路径是否正确。
    • 检查 cron 任务是否执行 (/etc/cron.daily/logrotate)。
    • 手动运行 logrotate -f 查看错误信息。
    • 检查状态文件中的最后轮替时间。
    • 确保满足轮替条件(文件大小、时间间隔)。
  • 新日志文件权限错误(服务无法写入):
    • 最常见原因! 检查配置中的 create mode owner group 是否设置正确,新文件所有权和权限是否与运行服务的用户匹配。
    • 如果是 SELinux 问题,检查 /var/log/audit/audit.log 或执行 ausearch -m avc --start recent,可能需要 chcon 修改上下文或使用 semanage fcontext + restorecon
    • 尝试使用 su owner group 指令。
  • 服务丢失轮替后的新日志(不写入新文件):
    • 最常见原因! 检查 postrotate 脚本是否正确发送了重载/重开信号 (HUP, USR1, USR2),信号是否被应用程序支持。
    • 检查 PID 文件路径在 postrotate 脚本中是否拼写正确。
    • 如果使用 copytruncate,确保应用程序能继续写入截断后的文件(大多数应用可以)。如果应用使用文件偏移量,则 copytruncate 不适用
  • postrotate 脚本未执行:
    • 确保启用了 sharedscripts
    • 检查脚本是否有语法错误(尤其是引号和反斜杠)。
    • 检查脚本执行权限(如果脚本是外部文件)。直接写在配置里的脚本块不需要权限。
  • 磁盘空间未释放(旧文件没删):
    • 检查 rotatemaxage 设置是否太保守。
    • 检查 notifempty 是否导致空文件未被轮替删除。
    • 使用 maxsize 删除过大的旧文件。
  • 归档文件没有被压缩:
    • 确保配置了 compress
    • 检查 delaycompress 是否生效(最近一轮未被压缩是正常的)。
  • logrotate -d 输出错误:
    • 仔细阅读输出,通常是配置指令语法错误、路径错误或变量引用问题。

9. 总结#

logrotate 是 Linux 服务器管理不可或缺的工具,为日志文件提供了一套成熟、灵活且自动化的生命周期管理机制。通过深入理解其配置文件 /etc/logrotate.conf/etc/logrotate.d/* 的选项(如轮替条件 rotate/size/maxage/maxsize,压缩 compress/delaycompress,新文件创建 create,权限设置 su,以及服务通知 postrotate/sharedscripts),管理员可以高效地:

  • 防止磁盘耗尽: 严格控制日志文件数量和历史保留。
  • 提高运维效率: 自动化执行轮替、压缩、删除等繁琐任务。
  • 确保合规性: 精确控制日志保留时间以满足审计要求。
  • 保障服务可用性: 通过正确的服务通知避免服务日志写入中断。 掌握配置的最佳实践(尤其是权限设置和避免不必要的 copytruncate)并熟练使用调试命令(logrotate -d -f)是成功部署 logrotate 的关键。将其作为服务器基线配置的一部分,对维护系统稳定性和可管理性至关重要。

10. 参考资源#