应基于修改时间(-mtime)而非创建时间判断日志过期,配合-type f和-name "*.gz"等限定后缀,先-print验证再-delete,避免误删;注意文件名日期与mtime不一致时需结合业务逻辑综合判定。

Linux上用find配合gzip或tar做日志轮转很常见,但“自动删除过期压缩日志”这事儿,关键不在删,而在**怎么准确定义‘过期’且不误删**——尤其当目录里混着未压缩的原始日志、.gz、.tar.gz、甚至带日期后缀和不带后缀的文件时。
用find按修改时间删压缩日志最稳妥
别信“创建时间”,Linux下stat显示的Birth时间多数不可靠,find默认的-mtime(基于修改时间)才是生产环境唯一可依赖的依据。压缩日志一旦生成,几乎不会再被修改,所以-mtime +30表示“修改时间早于30天前的文件”是合理策略。
- 必须加
-type f,避免误匹配目录 - 用
-name "*.gz"或-name "*.tar.gz"限定后缀,比用-regex更轻量、兼容性更好 - 先用
-print试运行,确认列出的文件确实是你想删的,再换-delete find /var/log/app -type f \( -name "*.gz" -o -name "*.tar.gz" \) -mtime +30 -print
注意gzip和tar生成的文件时间戳差异
gzip压缩后,目标文件的mtime会被更新为压缩完成时刻;而tar -czf打包时,归档内每个文件保留原始mtime,但.tar.gz这个外层文件本身的mtime仍是打包完成时间。也就是说:你看到的/var/log/app/access.log-20240101.tar.gz的时间戳,反映的是它被打包出来的那一刻,不是里面日志的最后一条记录时间。
Linux系统管理专家,覆盖12大模块:用户权限、SSH、存储、网络、systemd、防火墙、日志监控、备份恢复、TLS证书、Ansible、容器、IaC。提供配置、验证、加固、监控、备份、自动化、故障排查、回滚闭环。关键词:useradd、sudo、sshd_config、chmod、SEL...
- 如果你的日志切割脚本是先
mv access.log access.log-20240101再gzip,那mtime基本等于切割时间,-mtime +30可直接用 - 如果用了
logrotate且配置了dateext和compress,它默认用gzip,同样适用-mtime - 但若有人手动
cp旧日志再gzip,mtime就变成复制+压缩时刻,可能比实际内容新得多——这时得结合文件名里的日期解析,不能只信mtime
避免rm -rf硬删导致定时任务失败
直接写rm -f /var/log/app/*.gz看似简单,但有两大风险:一是shell通配符在无匹配文件时会原样传给rm,报rm: cannot remove ‘*.gz’: No such file or directory,可能让crontab误判任务失败;二是没限制路径深度,可能跨目录误删。
- 永远优先用
find ... -delete,它天然跳过无匹配情况,退出码稳定为0 - 如果非要用
rm,加上nullglob选项:shopt -s nullglob; rm -f /var/log/app/*.gz - 在crontab里调用脚本时,建议重定向stderr到日志:
0 2 * * * /usr/local/bin/clean-logs.sh >> /var/log/clean-logs.log 2>&1 - 别把
find命令直接塞进crontab一行,出错难排查,封装成脚本更可控
真正容易被忽略的,是日志文件名里隐含的时间和mtime不一致时的处理逻辑——比如一个叫app-error-20230615.log.gz的文件,mtime却是昨天,说明它刚被重新下载或解压再压缩过。这时候删它,可能丢掉还没归档的近期数据。判断“过期”必须结合业务场景,不能只看一个时间戳。

















