启用 copytruncate 指令可实现日志“复制并截断”,适用于无法响应信号的长期运行进程;须置于具体日志配置块内,推荐配合 size 限值使用,并避免与 create、postrotate 或全局配置混用。

在 Linux 中让 logrotate 轮转时“复制并截断”原日志文件,核心就是启用 copytruncate 指令。它适用于那些无法响应信号、日志句柄长期持有、又不能停机的程序(比如旧版 MySQL 错误日志、自研 C 服务、容器中无信号透传的进程)。
配置位置和基本写法
copytruncate 必须写在具体日志路径的配置块内,不能放在全局段(如 /etc/logrotate.conf 的顶部)。推荐做法是在 /etc/logrotate.d/ 下为应用单独建文件,例如:
- /etc/logrotate.d/myapp
内容示例(轮转 /var/log/myapp/app.log,超 100MB 即触发):
/var/log/myapp/app.log {
size 100M
rotate 5
compress
missingok
notifempty
copytruncate
}
注意:copytruncate 独占一行,不带参数,也不需要配 create 或 postrotate——它不新建文件,而是直接清空原文件内容,保留 inode、权限和属主。
为什么必须搭配 size 而非 daily?
copytruncate 是“复制 + 截断”两步操作,中间存在毫秒级窗口。若用 daily,在业务高峰时轮转一个几 GB 的日志,可能引发:
- 日志丢失:复制未完成,新写入内容被截断清空
- I/O 尖峰:一次复制读 + 截断写,磁盘负载翻倍
改用 size 100M 可把单次轮转控制在百 MB 级别,降低风险。大日志建议设更小值,如 size 20M。
常见误区和避坑点
以下操作会破坏 copytruncate 的预期行为:
- 在同一配置块里加 create:copytruncate 不创建新文件,create 会被忽略且可能干扰权限逻辑
- 加 postrotate 并发信号(如 kill -USR1):程序根本不需要重开日志,加了无效,还可能引发竞争
- 把配置写进 /etc/logrotate.conf 全局段:容易被其他规则覆盖,也违背模块化管理原则
- 忽略文件权限:确保 logrotate 进程有读原日志、写归档目录的权限,否则复制失败
验证是否生效
不要等 cron 自动触发,用命令手动验证:
- 查执行逻辑:
logrotate -d /etc/logrotate.d/myapp(调试模式,只打印不执行) - 强制轮转:
logrotate -f /etc/logrotate.d/myapp(立即执行,观察 /var/log/myapp/ 下是否生成 .1 文件且原 app.log 大小归零
成功后,app.log 的 inode 不变,ls -i 可确认;tail -f 仍能持续看到新日志追加,说明程序完全无感。











