首页/系统/Linux 运维命令速查/场景:日志压缩归档与过期清理
文件与目录76 条

场景:日志压缩归档与过期清理

磁盘告急清理的标准操作:先干跑核对范围,再压缩归档,最后按更老策略删除;全程空值保护、留痕可回溯。

Linux 运维命令速查系统更新于 2026-10-13

这个场景解决什么

磁盘告急时最怕手一抖删错东西,所以清理不是一个 rm 能了事,而是四步走:按时间条件圈定候选、干跑核对清单与占用总量、把「还想留但要省空间」的日志压缩成 .gz、把「已经过期」的归档删掉,最后核对空间回收量和文件完整性。全程用 NUL 分隔传递文件名(find -print0 配 xargs -0),带空格、引号甚至换行的文件名都不会被拆裂成多个参数。

基本信息

适用场景应急清理某个日志或临时目录;接管没人管的脏目录并建立留存规则
核心组合find 圈定时间范围 + du -ch --files0-from 统计 + xargs -0 + gzip/rm
前置动作df -h 确认哪个文件系统满,df -i 排除 inode 耗尽(这时删文件才有用)
风险等级高:删除不可逆。必须先干跑看清单,再执行动作

典型使用场景

  • 应急腾空间:/var/log 或某应用目录涨满,业务低峰期需要尽快回收容量
  • 接管脏目录:遗留目录长期没人管,需要建立分级留存规则(近 30 天原文、180 天内 .gz)
  • 搬迁前瘦身:整个目录要打包传输,先压缩历史文件减小体积
  • 审计前留证:保留期内的文件不删只压,保证仍能用 zcat 追溯内容
  • 固化成任务:把验证过的命令写进 cron,替代每次都人工登录处理

第 1 步:干跑核对

第 1 步:干跑核对
# 1) 先分清是容量满还是 inode 满,处理方式完全不同
df -h /var/log; df -i /var/log
# 2) 圈定候选:只打印清单,不执行任何动作
find /var/log/app -type f -name '*.log' -mtime +30 -print | head -50
# 3) 统计候选总量(前面用了 -print0,这里就配 --files0-from)
find /var/log/app -type f -name '*.log' -mtime +30 -print0 | du -ch --files0-from=- 2>/dev/null | tail -1
# 4) 确认候选里没有仍被进程打开的日志(正在写的别动)
find /var/log/app -type f -name '*.log' -mtime +30 -print0 | xargs -0 -r lsof 2>/dev/null | head

第 2 步:压缩历史日志

第 2 步:压缩历史日志
# -r 让候选为空时不执行,避免报错或被当成错误退出
find /var/log/app -type f -name '*.log' -mtime +30 -print0 | xargs -0 -r gzip -9
# 校验压缩包完整性:zcat -t 只测试不解压输出
zcat -t /var/log/app/app.log.2026-08-01.gz
# 看压缩比与回收情况
du -sh /var/log/app; df -h /var/log

第 3 步:删除更老的归档

第 3 步:删除更老的归档
# 只删 .gz,避免误伤刚产生的新日志
find /var/log/app -type f -name '*.log.gz' -mtime +180 -print | head
find /var/log/app -type f -name '*.log.gz' -mtime +180 -print0 | xargs -0 -r rm -v --
# 顺手清掉长期空目录(确认无人在用再删)
find /var/log/app -type d -empty -mtime +180 -print0 | xargs -0 -r rmdir

第 4 步:留痕与定时

第 4 步:留痕与定时
# 每步都追加到运维日志,事后能回答「删了哪些文件」
{ date -Is; df -h /var/log; } >> /var/log/ops/clean-$(date +%F).log
# 常态化为每日低峰任务(命令写进脚本再挂 crontab)
# 10 4 * * * /opt/ops/log-clean.sh >> /var/log/ops/log-clean.log 2>&1

建议的分层留存策略

文件年龄动作为什么
0-7 天不动当前滚动日志,进程正在写入,动它会导致句柄失效
7-30 天保留原文近期排障还要反复 grep,压缩后虽然能 zcat 但不如原文方便
30-180 天gzip -9 压缩文本日志压缩比通常能达到 5:1 以上,仍可追溯
180 天以上删除删除前核对合规与审计要求;只删 .gz,别碰新日志
长期方案是 logrotate 负责滚动与压缩、find 只兜底处理它管不到的目录。两套规则并行时,确保它们不对同一批文件重复动手,否则会出现「刚压完又被解压源覆盖」这类混乱。
脚本里用到的目录变量要先判空并确认不是根目录,再执行删除;变量为空时路径会被拼成 /,find 与 rm 组合会变成灾难。

易错点

  • -mtime +30 指「超过 30 乘 24 小时」,与按自然日划断的直觉有偏差,要按自然日加 -daystart,否则删除范围会比你预期多出将近一天
  • find 不带 -print0 或 xargs 不带 -0 时,文件名里的空格会把一个路径拆成多个参数,结果是删错对象;两者必须成对出现
  • 对仍被进程打开的日志执行 gzip:文件被替换,进程继续往已删除的 inode 写,磁盘空间不释放,日志也丢了,压缩前先用 lsof 排除这一批
  • 只删不记:没有把每步输出留痕到日志,事后无法回答删了什么、什么时候删的

数据来源与参考

  • man 1 find(GNU findutils 手册)
  • man 1 xargs(GNU findutils 手册)

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌