备份脚本的核心是可预期执行、即时失败告警和明确恢复路径;需用带转义时间戳的tar命令命名,捕获stderr验证成功,安全清理旧备份,优先rsync远程传输,并必须定期手动验证恢复。

直接说结论:备份脚本的核心不是“写得多漂亮”,而是“每次执行都可预期、失败能立刻发现、恢复路径明确”。
怎么用 tar 打包 + 时间戳命名,避免覆盖
常见错误是写成 tar -czf backup.tar.gz /data,下次运行直接覆盖,根本分不清哪次是哪次。
- 必须带时间戳:
tar -czf backup_$(date +\%Y\%m\%d_\%H\%M).tar.gz /data - 注意
date里的\%要转义,否则 shell 会报错或展开失败 - 建议统一用 UTC 或本地时区,别混用;如果服务器跨时区部署,优先用
date -u - 文件名里避免空格和冒号(
:在 Windows 下非法),所以用下划线和短横线更稳妥
如何判断 tar 是否真成功,而不是“看起来没报错”
tar 即使部分文件权限不足、路径不存在,也常返回 0(成功码),但实际漏打了关键目录。
- 加
--warning=no-file-ignored会掩盖问题,别开 - 真正可靠的是捕获 stderr 并检查非空:
tar -czf ... 2> tar.err && [ ! -s tar.err ] - 更进一步:用
tar -tzf xxx.tar.gz | head -n1验证压缩包可读且非空 - 别只依赖
$?,tar对很多错误静默容忍
备份前该删旧文件吗?用 find 还是 ls | head -n
留太多备份占磁盘,但删错了会导致无可用备份。重点不是“怎么删”,而是“删得安全可逆”。
- 用
find /backup -name "backup_*.tar.gz" -mtime +7 -delete简单但危险——-delete不回收站,误配-path就完蛋 - 推荐先 dry-run:
find /backup -name "backup_*.tar.gz" -mtime +7 -print,确认后再加-delete - 别用
ls | sort | head -n -3类方案:文件名含空格或特殊字符时会崩,且sort默认按字典序,backup_20241201会排在backup_2024201后面 - 更稳做法:用
stat -c "%y %n" *.tar.gz | sort | head -n -3 | cut -d' ' -f4-提取最老的几个文件名
远程备份到另一台机器,rsync 比 scp 强在哪
scp backup.tar.gz user@host:/backup/ 看似简单,但网络中断就全重传,大备份极不友好。
-
rsync -avz --partial --progress backup.tar.gz user@host:/backup/支持断点续传(--partial) - 加
--delete-after可同步清理远端过期备份,但务必先测试,避免误删 - 注意
rsync默认不校验内容一致性,加--checksum会变慢,一般用--size-only+ 文件名时间戳组合判断更实用 - 密钥登录必须配好,别在脚本里硬编码密码;用
ssh-agent或rsync --rsh="ssh -i /path/key"
真正的难点不在语法,而在于“恢复验证”——你写的脚本从没跑过恢复流程,那它就不是备份脚本,只是归档脚本。每周挑一个备份,手动 tar -xzf 到临时目录,diff -r 对比原路径,这个动作不能省。

















