应按时间戳+命名规范安全清理备份文件,使用find -mtime +7配合锁机制和磁盘空间检查,避免误删、冲突与撑爆磁盘。

备份文件堆积导致磁盘满,df -h 显示 /var 或 /backup 使用率 100%
直接删最老的备份不保险——可能刚好删掉还没被校验过的那轮,或误删正在写入的临时文件。得靠时间戳+命名规范来安全识别可清理项。
- 确保备份脚本生成的文件名含日期,比如
backup_20240520.sql.gz,不用backup_latest.sql.gz这类模糊名 - 用
find按修改时间(不是创建时间)筛选,因为gzip写完才改 mtime,更可靠 - 先测试再执行:把
rm换成echo看会删哪些文件,确认无误再放开
用 find + -mtime 安全清理 7 天前的 .sql.gz 文件
-mtime +7 表示“修改时间超过 7×24 小时”,不是“7 天前”,这点容易错——今天是 5 月 20 日,+7 实际清理的是 5 月 12 日及更早的文件,而非 5 月 13 日的。
- 推荐命令:
find /backup -name "*.sql.gz" -mtime +7 -delete - 如果系统不支持
-delete(如旧版 CentOS),改用-exec rm {} \; - 加
-maxdepth 1防止误入子目录,比如/backup/old/里有手动存档 - 务必加
2>/dev/null忽略权限错误提示,否则 cron 里报错容易掩盖真问题
shell 脚本里要加锁,避免多个备份/清理任务同时跑崩磁盘 I/O
没锁的情况下,凌晨 2 点备份和 3 点清理可能撞上,mysqldump 写一半,find -delete 扫到它、删掉临时文件,备份就残了。
- 用
flock最省事:flock -n /tmp/backup.lock -c "your_backup_command" - 清理脚本也用同一把锁:
flock -n /tmp/backup.lock -c "find ... -delete" -
-n是关键——抢不到锁立刻退出,不阻塞,让 cron 下次重试 - 别用
ps | grep自己实现锁,竞态条件多,且grep自身进程会被误匹配
备份脚本本身要控制单次大小,防止单个 .sql.gz 把磁盘撑爆
大库导出时若没分卷,一个 mysqldump 可能生成 20GB 临时文件,而清理脚本按天删,来不及救火。
- 对超 2GB 的库,强制用
--skip-extended-insert减小内存峰值,或配合split分卷:mysqldump ... | gzip | split -b 500M - backup_part_ - 在备份脚本开头加空间检查:
[ $(df /backup | awk 'NR==2 {print $5}' | sed 's/%//') -gt 85 ] && exit 1 - 清理逻辑不能只看文件年龄,也要看剩余空间——
df /backup低于 10% 时,强制多删 2 天的备份
事情说清了就结束。真正难的不是写脚本,是确认每个环节都踩过坑:锁有没有漏、-mtime 算对没、df 检查有没有被管道截断、gzip 进程崩溃后残留的 .sql 临时文件要不要一并扫——这些细节不验证,脚本越“自动”,出事越晚发现。











