事情要从上个月说起。我那台跑着Debian 12的NAS,一直用rsync做本地备份,每天凌晨2点把重要数据从主硬盘同步到一块冷备盘上。用了快两年,从来没出过问题,直到我发现一块4TB的WD Red硬盘开始报SMART错误。
当时我整个人是麻的。那块盘是冷备盘,平时不读写,就每天凌晨转个把小时。结果它先挂了,主盘反而活蹦乱跳。我赶紧把冷备盘的数据抢救出来,买了块新盘换上。但这件事让我开始怀疑人生——就一个rsync cron job,真的够用吗?
我原来的备份脚本长这样:
“`
rsync -avz –delete /mnt/main/ /mnt/backup/
“`
简单粗暴,同步过去,删除冷备盘上主盘已经删掉的文件。问题是,如果某天我不小心删了主盘上的关键文件,rsync跑完,冷备盘上对应的文件也会被删。这就是所谓的“同步即删除”陷阱。而且SMART报警告诉我,硬件故障不是靠软件能防的,我需要多一份冗余。
所以我决定调整备份策略。目标是:至少保留3个版本的历史快照,而且不能依赖单一存储介质。
第一个想法是用rsnapshot。这玩意基于rsync和硬链接,能实现增量快照,每次只保存变化的部分,但每个快照看起来都是完整的目录结构。我试了试,在Debian上安装很简单:
“`
apt install rsnapshot
“`
配置文件在/etc/rsnapshot.conf,需要指定备份目录和快照保存路径。我配了每天、每周、每月的快照保留策略。不过有个坑——rsnapshot要求备份目标目录和源目录在同一个文件系统里,因为硬链接不能跨分区。我的主盘是ext4,冷备盘也是ext4,但它们是两块不同的物理硬盘,挂载在不同的挂载点上。这就意味着,如果我把快照放到冷备盘上,硬链接就失效了,每个快照都会完整复制所有文件,磁盘空间直接爆炸。
试了一次,4TB的数据,做了3个快照,冷备盘直接撑爆。我当场骂了句脏话。
换个思路。既然硬链接跨不了分区,那就用BorgBackup吧。Borg是专门做去重备份的工具,支持压缩和加密,而且不依赖硬链接,它自己用块级别的去重算法。我在主盘上装好Borg:
“`
apt install borgbackup
“`
初始化一个仓库在冷备盘上:
“`
borg init –encryption=repokey /mnt/backup/borg_repo
“`
注意那个–encryption=repokey,它会生成一个密钥文件,如果丢了,备份就废了。我把它存在主盘的/root/里,又额外拷了一份到U盘上。
然后写备份脚本:
“`
#!/bin/bash
export BORG_REPO=/mnt/backup/borg_repo
export BORG_PASSPHRASE=’my-secret-phrase’
borg create –verbose –stats –compression lz4 \
::{now:%Y-%m-%d_%H:%M} \
/mnt/main/documents \
/mnt/main/photos \
/mnt/main/configs \
–exclude ‘/mnt/main/downloads’
borg prune –keep-daily 7 –keep-weekly 4 –keep-monthly 6
“`
这里我用了lz4压缩,速度快,压缩率不高但够用。–stats会打印每次备份的统计信息,方便检查。prune命令负责清理旧快照,保留最近7天的每日、最近4周的每周、最近6个月的每月。
第一次跑备份,4TB的数据,去重后实际只用了2.3TB,因为很多文件是重复的(比如同一个软件包在多个目录下)。Borg的块去重确实牛逼,它把文件切成小块(默认64KB),只存储不重复的块。
但用了两周,我发现一个问题:Borg的备份速度比rsync慢很多。增量备份还好,但全量备份那一次跑了整整18个小时。而且每次备份时,CPU占用率飙到80%以上,因为要计算块的哈希值做去重。我那台NAS是N5105的CPU,性能本来就一般,备份期间其他服务(比如Jellyfin)明显卡顿。
我琢磨了一下,决定把策略改成“双层备份”:日常用rsync做快速同步,保证数据实时性;每周用Borg做一次全量快照,作为历史版本存档。
脚本改成这样:
“`
# 日常rsync同步(每天凌晨2点)
rsync -avz –delete /mnt/main/ /mnt/backup/latest/
# 每周六凌晨3点用Borg做快照
if [ $(date +%u) -eq 6 ]; then
borg create –verbose –stats –compression lz4 \
::{now:%Y-%m-%d_%H:%M} \
/mnt/backup/latest
borg prune –keep-daily 7 –keep-weekly 4 –keep-monthly 6
fi
“`
这样,冷备盘上始终有一个最新的完整副本(通过rsync),同时Borg仓库里保留了历史快照。如果主盘挂了,直接用rsync的副本恢复,快;如果误删了文件,从Borg仓库里找出旧版本,慢但稳妥。
不过又踩了一个坑。rsync的–delete选项会删除冷备盘上主盘不存在的文件,但Borg仓库里的快照是独立的,不受影响。然而,如果我在rsync同步后、Borg快照前删了主盘上的文件,那么rsync同步到冷备盘时,那个文件就没了,Borg快照里也不会包含它。所以rsync和Borg的执行顺序很重要——必须保证Borg快照在先,rsync在后。但我上面的脚本顺序写反了,应该先Borg再rsync,确保快照包含所有文件,哪怕主盘马上要删。
改一下:
“`
if [ $(date +%u) -eq 6 ]; then
borg create … /mnt/backup/latest
fi
rsync -avz –delete /mnt/main/ /mnt/backup/latest/
“`
这样,周六先基于当前冷备盘的完整副本做Borg快照,然后rsync把主盘的最新状态同步过来。即使主盘有误删,Borg快照里还保留着之前的版本。
测试了几周,效果还行。但还有一个隐患——冷备盘本身还是单点故障。如果冷备盘坏了,rsync副本和Borg仓库全丢。我考虑过再加一块盘做RAID1,但NAS机箱没位置了。后来买了个外置USB硬盘盒,每个月手动把Borg仓库冷备份到那块盘上,放公司抽屉里。
顺便说一句,Borg的加密功能在恢复时有个坑。如果你用了repokey加密,恢复时需要输入密码和密钥文件。我之前把密钥文件存在主盘上,如果主盘挂了,密钥也挂了,那就彻底完了。所以必须把密钥文件单独存到安全的地方。我把它打印成二维码贴在了机箱内侧,又存了一份在密码管理器里。
还有,Borg的版本号也很重要。我一开始装了apt源里的1.2.4,结果发现prune命令有个bug,在特定条件下会误删快照。升级到1.2.7才修好。建议直接去GitHub下载最新release,或者加Borg的官方PPA。
最后说一下恢复测试。我模拟了一次灾难场景:把主盘拔掉,尝试从冷备盘的rsync副本恢复。过程很简单,直接把/mnt/backup/latest/ rsync回去就行。然后我又模拟了误删文件,从Borg仓库恢复某个旧版本:
“`
borg extract /mnt/backup/borg_repo::2024-11-15_03:00 /mnt/main/documents/lost_file.txt
“`
恢复速度还行,但Borg extract会把文件解压到当前目录,路径是完整的,比如./mnt/main/documents/lost_file.txt,需要手动挪回去。
总结一下踩的坑:
1. 别迷信rsync的–delete,它会在你误删时帮倒忙。历史快照是必须的。
2. 硬链接跨不了分区,rsnapshot在这种场景下不适用,除非你把所有数据放一个文件系统里。
3. Borg的块去重效率高,但CPU开销大,低功耗设备上要考虑备份时间窗口。
4. 加密备份一定要保管好密钥,否则就是给自己挖坟。
5. 定期做恢复测试,别等真出事了才发现备份文件是坏的或恢复流程不对。
现在的备份策略是:rsync做每日实时同步 + Borg做每周增量快照 + 每月外置硬盘冷备份。3-2-1原则(3份数据,2种介质,1份异地)勉强算达标了。虽然折腾了快一个月,但至少晚上能睡踏实了。
📎 延伸阅读
看完这篇,如果你想:
- 直接拿工具 → 回复”13“,我把跨境获客工具包发给你
- 系统学习 → 点击菜单”AI训练营”,从0开始跑通AI变现