Linux logrotate rotate 后应用仍写旧文件怎么办
来源:17golang原创
时间:2026-09-11 16:11:00 285浏览 收藏
执行 logrotate -f 后,如果新建的 app.log 一直是空的,而 app.log.1 还在变大,通常不是 rotate 没有执行,而是应用进程仍握着轮替前文件的文件描述符。路径被改名后,已经打开的描述符不会自动跟随新路径。
先查进程的/proc/,确认它写的是带有/fd deleted或旧后缀的 inode;能安全重载就用postrotate让应用重新打开日志,无法重载时才考虑copytruncate。
- rename 只改变目录项,进程已打开的文件描述符仍指向原 inode。
- 优先使用应用支持的 reload、HUP 或专用 reopen 动作,而不是盲目重启。
- copytruncate 兼容不能重载的程序,但复制和清空之间存在极短的数据窗口。
为什么 rotate 后应用还写旧文件
普通轮替大致分成三个动作:把当前日志改名、按原路径创建新文件、执行 postrotate。logrotate 手册明确说明,新文件会在 postrotate 之前创建。对应用来说,打开日志时拿到的是一个文件描述符和 inode,不是每次写入都重新按字符串路径查找文件。因此,旧描述符仍可能落到 app.log.1,新建的 app.log 则无人写入。
这也解释了“目录里明明有新文件,应用却写旧文件”的现象。不要先把问题归咎于权限;如果旧文件的大小持续变化,第一判断应是应用没有重新打开日志。

先用文件描述符确认是不是旧 inode
先找出实际写日志的进程,再查看它的打开文件。下面的命令只读系统状态,不会触碰日志内容:
# 找出应用主进程,并列出它打开的日志描述符
pid=$(pgrep -xo myapp) # 替换为实际进程名,-x 避免匹配相似名称
ls -l "/proc/$pid/fd" | grep '/var/log/myapp/app.log' # 查看描述符最终指向
# 也可以按 inode 对比当前文件与轮替文件
stat -c '%i %s %n' /var/log/myapp/app.log /var/log/myapp/app.log.1 # 输出 inode、大小和路径
如果 ls 结果显示描述符指向 app.log.1,或出现“已删除”的旧路径,就说明应用还没有 reopen。Linux 内核文档把 /proc/ 定义为进程当前打开文件的符号链接;这比只看文件名更接近真实写入目标。若找不到日志描述符,再检查应用是否经由 journald、syslog 或容器标准输出记录,不能把所有“旧文件”都归为 logrotate。
能重载应用时用 postrotate 让它重新打开
应用支持日志重开时,推荐让它完成一次无损或低影响的 reload。常见做法是在轮替完成后调用服务自己的重载命令:
/var/log/myapp/app.log {
daily # 按天轮替,实际周期按业务吞吐调整
rotate 14 # 保留 14 个归档文件
compress # 轮替后的文件再压缩
missingok # 文件暂时不存在时不让整轮任务失败
notifempty # 空文件不触发轮替
create 0640 app app # 用原路径创建新文件并设置属主
postrotate
systemctl reload myapp # 仅使用该服务已实现的 reload 动作
endscript
}
systemctl reload 是服务级操作,是否真的重新打开日志取决于 unit 的 ExecReload 和应用实现;它不等同于 systemctl daemon-reload。如果应用文档明确要求发送 HUP,也可以在 postrotate 中使用目标主进程的 HUP,但不要把 HUP 当作所有程序通用的 reopen 信号。多日志共用一个服务时再评估 sharedscripts,避免同一轮重复触发重载。

不能重载时用 copytruncate 但接受窗口风险
如果程序没有 reopen 能力,或者重载会造成不可接受的中断,可以使用 copytruncate。它先复制当前内容,再把原文件原地截断为零;应用继续持有的描述符仍对应同一个 inode,所以后续写入会回到原路径。
/var/log/legacy/app.log {
weekly # 低频写入的遗留程序可按周轮替
rotate 8 # 保留八份归档
copytruncate # 复制后原地清空,避免依赖应用 reopen
compress # 归档文件压缩保存
delaycompress # 把刚轮替的文件留到下一轮再压缩
missingok # 兼容程序偶尔不创建日志的情况
}
这个方案的代价不能省略:复制与截断之间存在很小的时间片,恰好写入的内容可能没有进入归档;高并发、大日志或不能接受任何丢行的审计日志不宜默认采用它。能改应用时,增加显式 reopen 或把日志交给 journald、syslog 等专门收集器通常更稳。
| 场景 | 优先选择 | 需要接受的边界 |
|---|---|---|
| 应用有可靠的日志重载 | postrotate + 服务 reload | reload 必须确实关闭并重新打开日志 |
| 应用不能被通知 reopen | copytruncate | 复制与截断之间可能丢少量写入 |
| 日志由 journald/syslog 接管 | 按收集器的轮替策略处理 | 不要再对错误的文件路径重复轮替 |
验证新文件与归档文件都在增长
修完配置后先用调试模式确认匹配到正确的文件,再强制轮替一次。调试输出只用于查看计划,不会真正改文件:
# 先确认规则匹配,-d 只打印计划,不执行轮替
logrotate -d /etc/logrotate.conf # 检查路径、周期和 postrotate 是否被读取
# 确认无误后再在维护窗口强制轮替
logrotate -f /etc/logrotate.conf # 生产环境应先确认状态文件和权限
# 轮替后再次查看当前文件的 inode、大小和最近修改时间
stat -c '%i %s %y %n' /var/log/myapp/app.log /var/log/myapp/app.log.1 # 对比新旧文件
tail -n 5 /var/log/myapp/app.log # 只抽查新文件是否出现新的日志行
使用 reopen 路径时,新的 app.log 应出现新的 inode,应用的 /proc/ 应重新指向它;使用 copytruncate 时,inode 通常保持不变,但文件会先降到较小体积后继续增长。若两者都没有发生,回到三项基础检查:规则是否被主配置 include、运行 logrotate 的用户是否有权限、应用实际日志出口是否真的是这个文件。
常见问题
只加 create 为什么不能解决旧文件问题?
create 只负责按原路径建立新文件,不会替应用关闭旧描述符;仍需 reload、HUP 或 copytruncate。
postrotate 里应该用 reload 还是 restart?
优先用应用官方支持且能重新打开日志的 reload;没有可靠 reload 行为时才评估 restart,并把中断、连接和状态恢复纳入维护窗口。
看到 deleted 就一定是 logrotate 配置错了吗?
不一定。deleted 说明目录项已被移除但进程仍持有描述符,常见于轮替,也可能来自应用自身的清理逻辑;应结合轮替时间和配置一起判断。
排查这类问题的关键不是反复执行 logrotate -f,而是确认“谁持有 inode、谁负责 reopen”。先用文件描述符拿到证据,再按应用能力选择 postrotate 或 copytruncate,最后用新旧文件的 inode 和增长情况收口。
-
426 收藏
-
387 收藏
-
242 收藏
-
238 收藏
-
402 收藏
-
275 收藏
-
文章 · linux | 3小时前 | Linux · 文件系统 · 挂载 · 运维排障 · 工作目录 bind mount Linux mount --bind umount target is busy EBUSY476 收藏
-
244 收藏
-
115 收藏
-
429 收藏
-
384 收藏
-
207 收藏
-
255 收藏
-
392 收藏
-
268 收藏
-
185 收藏
-
160 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习