olddir 用于将轮转后的旧日志直接移动到指定目录,要求路径与日志文件同文件系统、为已存在的绝对路径且可写,移动发生在重命名后、压缩前,不支持跨挂载点。

使用 olddir 指定旧日志存放目录
logrotate 默认把轮转后的旧日志(如 app.log.1、app.log.2.gz)留在原目录,想挪到别的地方,必须用 olddir。它不是“备份到”或“复制到”,而是直接 移动 —— 轮转时原地重命名后立刻 mv 到目标目录。
注意:olddir 路径必须和日志文件在同一个文件系统(即不能跨挂载点),否则 logrotate 会报错并跳过该轮转块,错误信息类似:error: cannot move /var/log/app.log.1 to /backup/logs/app.log.1: Invalid cross-device link。
-
olddir必须是已存在的绝对路径,logrotate 不会自动创建目录 - 目标目录权限需允许 logrotate 进程(通常是 root)写入
- 不能和
create冲突:新日志仍会在原路径创建,olddir只影响旧文件 - 如果同时用了
compress,压缩动作发生在移动之后(即在目标目录里压缩)
olddir 和 sharedscripts 配合时的坑
当一组日志共用一个 postrotate 脚本(比如 reload nginx),且启用了 olddir,脚本里若引用了 $1 或硬编码原路径,很可能出错 —— 因为轮转后旧文件已不在原处。
例如这个配置:
/var/log/nginx/*.log {
daily
rotate 7
olddir /var/log/old-nginx
compress
sharedscripts
postrotate
/usr/sbin/nginx -s reload
endscript
}
看起来没问题,但如果你在 postrotate 里写了类似 ls /var/log/nginx/*.1 就会找不到文件 —— 它们全在 /var/log/old-nginx/ 下了。
- 脚本中避免依赖旧文件的原始位置
-
sharedscripts下所有日志共享同一段postrotate,不区分单个文件路径 - 如果真要操作旧文件,得明确写
/var/log/old-nginx/*.log.1
为什么不用 copytruncate + 手动 mv?
有人想绕过 olddir 限制,改用 copytruncate 然后在 postrotate 里 mv,这不可靠:
-
copytruncate是先复制再清空原文件,此时旧内容还在原路径临时存在,竞态下可能被重复处理 - 手动
mv在postrotate里执行,但 logrotate 已完成轮转逻辑,后续压缩、删除等步骤仍按原路径走,容易混乱 -
olddir是原子操作,由 logrotate 内部统一调度,更安全
除非你确定要跨文件系统,否则别自己拼凑替代方案 —— olddir 就是为此设计的,别绕。
调试时确认 olddir 是否生效
直接运行 logrotate -d 不会真正移动文件,但会打印详细步骤,关键看输出里有没有类似这行:
renaming /var/log/app.log.1 to /var/log/old-nginx/app.log.1
如果没有,检查三点:
- 配置文件语法是否正确(
olddir后面必须跟空格+绝对路径,不能换行) - 目标目录是否存在且可写(
ls -ld /var/log/old-nginx) - 是否被其他配置覆盖(比如
/etc/logrotate.conf里有noolddir,或/etc/logrotate.d/下其他文件冲突)
真实环境里最容易忽略的是目录不存在或权限不对 —— logrotate 不报错也不提示,只是静默跳过 olddir,旧文件照常留在原地。











