登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  linux

Linux logrotate配合postrotate通知服务重开日志的配置

来源:17golang原创

时间:2026-09-20 12:25:18 220浏览 收藏

我在排查“日志文件已经被改名,服务却还在往旧文件写”的问题时,最后把责任拆成两段:logrotate 负责完成轮转,服务负责重新打开同名的新文件。配置的关键不是简单加一条重启命令,而是让 postrotate 只在真的发生轮转后发出服务能理解的重开信号。

官方地址:https://github.com/logrotate/logrotate/

要点速览
  • sharedscripts 把通配路径匹配到的多份日志合并成一次通知。
  • postrotate 不是无条件执行;没有文件需要轮转时不会运行。
  • 先用调试模式看判断结果,再用强制运行和文件增长确认服务已经切到新文件。

先把轮转和重开职责分开

常见场景是服务持续打开 /var/log/myapp/app.log。logrotate 把它改名为 app.log.1,再创建新的 app.log;但进程手里的文件描述符仍然指向旧 inode。此时目录里虽然出现了新文件,服务并不会自动切换。

因此重开动作必须由服务提供支持。优先确认单元的文档或启动脚本是否约定了 HUPreload 或专用管理命令。不要把“重启服务”当成通用替代品:它会带来连接中断,且未必比重新打开日志更安全。

Linux logrotate轮转旧日志并通过postrotate向服务发送重开信号的结构说明图
图1:结构说明图,logrotate 只负责生成新日志文件,postrotate 再把重开信号交给服务。

用 sharedscripts 控制 postrotate 的触发次数

一个配置可能匹配 app.logaccess.logerror.log。默认情况下,脚本可能按每个实际轮转的文件触发;服务却通常只需要一次重开。把 sharedscripts 放在脚本块前,可以让这一组匹配文件共用一次 postrotate,减少重复信号。

/var/log/myapp/*.log {
    daily
    rotate 14
    missingok
    notifempty
    compress
    delaycompress
    sharedscripts
    postrotate
        # 仅在本组至少有一份日志完成轮转后,通知主进程重开日志
        systemctl kill -s HUP --kill-who=main myapp.service
    endscript
}

这里的 delaycompress 让刚轮转的上一份日志暂不立即压缩,便于某些仍需短暂读取旧文件的流程;它不是重开信号的替代品。若服务不识别 HUP,应把命令换成该服务明确支持的 reload 方式。

用调试模式确认 logrotate 真的会执行脚本

“postrotate 没反应”经常不是脚本坏了,而是当前轮转周期、文件大小或 notifempty 条件没有满足。先只做判断,不改文件:

# -d 只展示解析与轮转判断,不实际改名、压缩或发送信号
sudo logrotate -d /etc/logrotate.d/myapp

# 需要一次演练时再强制执行;执行前确认测试路径和服务名称
sudo logrotate -f /etc/logrotate.d/myapp

调试输出应能看到配置被读取、目标日志的轮转判断,以及是否跳过脚本。强制运行会改变日志文件,最好在维护窗口使用,并先保留当前配置副本。

logrotate调试结果与postrotate服务重开信号之间的排查关系说明图
图2:排查说明图,把“没有轮转”“脚本失败”和“服务仍写旧文件”分成三个不同证据层。

三类现象对应三种修复动作

现象先看什么处理方向
没有看到 postrotate 输出调试输出、周期、文件大小、notifempty先确认是否真的发生轮转,不要先改信号命令
出现 shared postrotate script errorsystemctl 状态、单元名、信号权限修正服务单元或改用支持的 reload 命令
新文件不增长,旧文件继续变大文件 inode、服务日志、重开后状态确认服务能重开日志,并在新文件产生写入后再收尾

如果服务使用独立用户运行,systemctl kill 往往比直接读取 PID 文件更不容易拿错进程;若只能使用 PID 文件,脚本必须检查文件非空、进程存在和退出码,避免把陈旧 PID 发给其他进程。

上线前留下可回滚的检查清单

  • 配置文件能被 logrotate -d 正常解析,花括号和 endscript 成对。
  • 服务单元名称、运行用户和重开信号已经与实际部署一致。
  • 强制演练后,旧日志被保留,新日志文件出现,且服务日志没有报告 reload 失败。
  • 观察一个自然周期,确认新文件持续增长;异常时先移除或恢复该配置,再检查服务自身日志。

常见问题

postrotate 会在每次定时任务都执行吗?

不会。目标文件没有满足轮转条件时,脚本不会执行;满足条件时才会在轮转后运行。

sharedscripts 是不是必须配置?

不是。只有一个日志文件时通常无须它;通配符匹配多文件并且服务只需一次重开时,它能避免重复通知。

发 HUP 后仍然写旧日志怎么办?

先确认服务是否把 HUP 定义为重开日志,再检查信号是否发给正确的主进程。若服务不支持 HUP,应改用官方约定的 reload 入口。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>