这个场景要解决什么
这是磁盘告警时的经典处置:按修改时间圈出历史日志,先数数量、看清单,再删除或归档。核心是 find 的 -mtime、-mmin 条件,删除动作用 -delete 或交给 xargs rm。全过程只有两步是安全的:先 -print 核对集合,再执行删除。跳过第一步直接在生产的目录上 -delete,是这类误删事故最常见的成因。
基本信息
| 适用场景 | 日志、临时文件按时间批量清理或归档 |
|---|---|
| 涉及命令 | find(-mtime / -mmin / -newermt / -delete / -print0)、xargs、tar、gzip |
| 权限要求 | 删除 /var/log 下的文件需要 root;-delete 要求对所在目录有写权限 |
| 安全原则 | 先预览后删除,范围写具体路径与具体模式 |
典型使用场景
- 磁盘使用率告警:清理 30 天前的轮转日志,为业务日志腾出空间
- 合规留存:先按保留期打包成 tar.gz 归档,再删除原件
- 定时清理:把这条命令放进 crontab,每天固定时间跑一次
- 临时文件回收:清掉 /tmp 下超过 2 小时未被修改的残留文件
- 应用日志分片:形如 app.log.1、app.log.2.gz 的轮转产物按时间统一处理
标准三步流程
标准三步流程
# 1. 先看清楚要删什么:只列清单
find /var/log/myapp -type f -name '*.log.*' -mtime +30 -print | head -50
# 2. 数量对不上预期就停下来查清原因
find /var/log/myapp -type f -name '*.log.*' -mtime +30 | wc -l
# 3. 确认无误再删除
find /var/log/myapp -type f -name '*.log.*' -mtime +30 -delete先归档再删除
先归档再删除
find /var/log/myapp -type f -name '*.log.*' -mtime +30 -print0 \
| tar --null -czf /backup/logs-$(date +%F).tar.gz --files-from=-
# 归档完成后再删原文件
find /var/log/myapp -type f -name '*.log.*' -mtime +30 -delete文件极多时的删法
文件极多时的删法
find /var/log/myapp -type f -name '*.log.*' -mtime +30 -print0 \
| xargs -0 -r rm -v
# -print0 与 xargs -0 配对,文件名含空格也不会拆错时间条件对照
| 条件 | 含义 | 适用 |
|---|---|---|
| -mtime +30 | 修改时间超过 30 个 24 小时周期 | 最常用的清理阈值 |
| -mtime -7 | 修改时间在最近 7 个 24 小时之内 | 找近期变动过的文件 |
| -mmin +120 | 修改时间超过 120 分钟 | 比 -mtime 更细的粒度 |
| -newermt '2026-09-01' | 修改时间晚于指定时刻 | 按自然日期圈范围 |
| ! -newermt '2026-10-01' | 修改时间早于指定时刻 | 与上一条组合出闭区间 |
上生产前先在测试目录演练一遍,清理范围必须写具体路径与具体模式,永远不要对 / 直接 -delete 或 -exec rm。日志还在被进程写入时,删除只是移除目录项,空间不会立刻释放。
更稳妥的做法是让应用或 logrotate 自己管留存(rotate N 加 maxage),把 find 删除只作为兜底,避免两套清理逻辑互相打架。
常见文件名模式
| 模式 | 匹配对象 | 处理建议 |
|---|---|---|
| *.log | 当前正在写的活动日志 | 一般不要删,文件被打开时删了也不释放空间 |
| *.log.1 | 上一轮轮转产物 | 超过保留期即可清理 |
| *.log.[0-9]* | 带编号或编号加压缩后缀的轮转产物 | 批量清理的主要目标 |
| *.gz | 已 gzip 压缩的历史日志 | 清理前确认归档策略 |
动手前的三项确认
- 确认文件没被进程打开:lsof +L1 挂载点,被打开的文件删了不释放空间
- 确认没有正在运行的归档或同步任务还会读这些文件,避免两边打架
- 确认清理范围写对了:路径末尾少一个斜杠、通配符多一个星号,都可能扫进完全不该动的目录
想先估算能腾出多少空间,用 -printf 输出字节数再求和:find 条件 -printf '%s\n' | awk '{s+=$1} END {printf "%.1f MB\n", s/1048576}',确认收益够大再执行删除。
-delete 与 -exec rm {} + 都不带确认环节。前者直接调 unlink,更快也不产生子进程,但同样不会提示你;两者都应先跑一遍 -print 核对集合。
清理策略要和归档策略对齐:如果归档任务每周才跑一次,删除阈值就不该短于一周,否则会出现「还没归档就已经被删掉」的空窗期。
把这条命令放进 crontab 时建议给任务加锁(flock),避免上一轮还没跑完下一轮又启动,两轮清理同时扫描同一目录会互相干扰,也让日志难以解读。