-mtime +7 实际只保留6天,因它按整24小时向下取整到当日00:00:00;要真正保留最近7天,须用 -mtime +6。

直接用 find 按修改时间删最可靠,但必须用 -mtime +6(不是 +7)才能真正保留最近 7 天;-ctime 和文件名日期匹配都容易误判,尤其当备份被 rsync 同步或 touch 过。
为什么 -mtime +7 实际只留 6 天?
-mtime 计算的是“整 24 小时段”,向下取整到当天 00:00:00。今天是 2026年6月7日 07:38,-mtime +7 删除的是最后修改时间 ≤ 2026年5月30日 00:00:00 的文件——中间差近 22 小时。要留满 7 天,得用 -mtime +6。
-
-mtime 0:过去 24 小时内(即 6月6日 07:38 之后) -
-mtime +6:≤ 6月1日 00:00:00 → 覆盖 6月1日 00:00 到 6月7日 07:38 之间生成的全部有效备份 - 若备份脚本固定在每天 02:00 执行,用
+6才能确保 6月1日 02:00 的文件撑到 6月8日 02:00 后才被删
如何避免误删正在写的 .part 或二进制日志?
备份目录里混着临时文件、锁、mysql-bin.000001 等,不加过滤的 find /backup -delete 极易出事。必须显式限定范围:
- 只操作普通文件:
-type f - 限定扩展名:
-name "*.sql.gz" -o -name "*.xbstream" -o -name "*.zst" - 排除临时后缀:
! -name "*.part" ! -name "*.tmp" - 防止钻子目录:
-maxdepth 1 - 先测试再执行:
find /backup/mysql -maxdepth 1 -type f \( -name "*.sql.gz" -o -name "*.xbstream" \) ! -name "*.part" -mtime +6 -print
当备份文件名含日期(如 backup_20260601.sql.gz),还能信 -mtime 吗?
不能轻信。rsync、scp、touch 都会重置 -mtime,导致“新名字旧时间”或“旧名字新时间”。此时应优先按文件名解析日期:
- 用
date -d "7 days ago" +%Y%m%d得到阈值(如 20260531) - 用正则匹配文件名中的 8 位日期:
find /backup/mysql -name "backup_*.sql.gz" -exec sh -c '[[ $(basename "$1") =~ backup_([0-9]{8})\.sql\.gz ]] && [[ ${BASH_REMATCH[1]} -lt 20260531 ]] && rm "$1"' _ {} \; - 该方式绕开文件系统时间,适合对一致性要求高的生产环境
crontab 里跑 find 为什么总失败?
root 的 crontab 默认 PATH 极窄(常只有 /usr/bin:/bin),find 可能找不到,-delete 在旧版 find(如 CentOS 6)中也不支持。
- 在 crontab 中写全路径:
/usr/bin/find /backup/mysql ... -exec /bin/rm {} \; - 显式设置环境:
PATH=/usr/local/bin:/usr/bin:/bin - 重定向错误输出:
>/var/log/cleanup.log 2>&1 - 别依赖
-delete:它在某些系统上不可用,-exec rm {} \;更通用
真正难的不是写命令,而是确认哪些文件“确实过期且无主”。比如一个 .part 文件,-mtime +6 满足,但它可能正被备份脚本写入;又比如 mysql-bin.000001,名字像备份,实则是二进制日志,该由 expire_logs_days 管。清理前务必人工抽检几个目标文件,看它们是否还在被进程占用(lsof -n | grep /backup)、是否在备份脚本的命名白名单里、是否属于其他生命周期管理机制。











