现场是这样的。一台 CentOS 7 上把 40G 的备份从 /data 移到 /backup,中途手动 ctrl+c,之后 /data 里的原文件不见了,/backup 下同名文件大小是 0,两边的目录都还在。

中间走过弯路,把「源目录项只在拷贝成功后才删除,可分布式存储上删除和拷贝的顺序不可控」当成主因,改完现象没变。

排查方向其实有限,先把可能性排一排。跨文件系统时 mv 实际是拷贝加删除,拷贝没完成前中断会留下不完整的目标文件;mv 先创建目标文件再写内容,中断后文件存在但长度为零;脚本里没有校验返回码,静默失败被当成成功继续往下跑。

第一件事是确认还有没有完整副本

ls -l /backup/*.tar.gz /data/*.tar.gz 2>/dev/null

从快照或者备份里找回原文件

ls -lt /snapshot | head -5

接着改用带校验的拷贝再删源

rsync -aHAX --info=progress2 /data/bak.tar.gz /backup/ && sha256sum /data/bak.tar.gz /backup/bak.tar.gz

校验一致后再删掉源文件

cmp /data/bak.tar.gz /backup/bak.tar.gz && rm -f /data/bak.tar.gz

别只看报错消失,验证要多做一步。两侧 sha256 完全一致,目标文件大小与源文件相同,删除源文件后 df 显示 /data 空间已释放且 /backup 占用相应增加。

大批量迁移一律用 rsync 加校验再删源,mv 只适合同一文件系统内的重命名;中断过的目标文件要当废文件删掉,不要接着用。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。

作者 9823189