摘要
在 Raspberry Pi 等长期运行设备中,SD 卡依然是最常见、也是最不可靠的存储介质之一。
异常断电、磨损老化或 silent corruption 往往在系统仍可运行时悄然发生,一旦彻底失效,恢复成本极高。
本文记录了一套 与设备物理位置无关的 Raspberry Pi 灾备方案:
通过公网 SSH,以 备份机主动拉取(pull) 的方式,对远端树莓派的根文件系统进行 持续增量备份,在不影响系统运行的前提下,确保随时具备完整恢复能力。
设计目标
- 不依赖树莓派所在网络环境(局域网 / 公网均可)
- 不要求设备主动推送数据
- 系统运行状态下即可执行
- 保留文件的完整属性(权限 / ACL / xattr / UID/GID)
- 使用固定目录,始终保持“最新可恢复镜像”
- 操作可压缩为一次脚本执行
总体设计思路
1. 连接模型:Pull 而非 Push
备份由 备份机主动发起:
- 树莓派只需提供 SSH 访问
- 不保存外部写入凭据
- 不承担备份调度职责
该模型符合最小权限原则,也更适合嵌入式设备长期运行。
2. 标识方式:域名而非 IP
使用域名作为唯一入口:
- 不关心设备位于何处
- 不依赖固定 IP
- 网络变化不影响备份逻辑
只要 SSH 可达,系统即可被完整拉取。
3. 备份粒度:文件级增量镜像
放弃块级复制(dd),采用 rsync:
- 支持目标盘小于源盘
- 避免读取潜在坏块
- 天然支持增量同步
- 更适合 SD 卡存在早期隐性损坏的场景
核心实现
rsync 参数选择
关键参数说明:
| 参数 | 作用 |
|---|---|
-a | 保留权限、时间戳、符号链接 |
-A | 保留 ACL |
-X | 保留扩展属性 |
-H | 保留硬链接 |
--numeric-ids | 避免 UID/GID 映射错误 |
--delete | 目标端保持为真实镜像 |
--info=progress2,stats,name | 显示总体进度、文件名与统计信息 |
排除运行态目录:
/dev
/proc
/sys
/run
/tmp
/mnt
/media
/lost+found
/snap
最终命令形式(公网 Pull 模式)
sudo rsync -aAXH \
--numeric-ids \
--delete \
--info=progress2,stats,name \
--exclude={...} \
-e "ssh -p <PORT>" \
root@<DOMAIN>:/ \
<LOCAL_BACKUP_DIR>
说明:
- 备份机以 root 执行,确保可完整还原权限
- 使用 SSH 公钥登录,无需交互
- 目标目录为固定路径,每次执行即完成一次增量同步
运行结果解读
典型输出特征:
- 仅同步日志、状态文件(如
/var/log、journal) - 实际传输数据量为数 MB
- 总体 size 数 GB,speedup 通常达到数百至上千
这表明:
系统主体保持稳定,仅有预期变化被同步。
这是增量备份正常、健康工作的表现。
脚本化与长期使用
将上述命令封装为脚本后:
- 不再需要记忆复杂参数
- 执行成本等同于“确认系统仍可恢复”
- 可在任意时间、任意地点触发备份
进一步可选增强(非必须):
- 使用
flock防止并发执行 - 输出简单完成标记
- 后续再考虑 cron 自动化
能力边界与价值
该方案并不追求:
- 历史版本回溯
- 快照级一致性
- 高频实时同步
而是明确聚焦于:
“只要系统还能 SSH,就能完整回收其当前状态。”
在 SD 卡存在不可预测失效风险的前提下,这是一个工程上性价比极高、心智负担极低的长期策略。
结语
经历过一次存储介质故障后,与其寄希望于“不再发生”,不如建立可重复、可执行、可验证的恢复能力。
通过公网 pull 模式 + rsync 增量镜像,
Raspberry Pi 不再是一个“位置相关的脆弱设备”,
而是一个随时可以被完整取回的远端节点。