我的服务器备份体系搭建全记录
本文记录于 2026-05-28,基于 Oracle ARM Ubuntu 20.04 LTS 环境,折腾了一整个下午才搞定。
背景
服务器上跑着一堆服务:两个 Typecho 博客、一个 OpenClaw AI 中台、各种 Docker 容器(PhotoPrism、BitWarden、alist 等),还有 Java/Python 微服务。每天凌晨把这些东西自动备份到 OneDrive,并且要求:
- 每天自动执行
- 备份完推送 Telegram 通知
- 保留 7 天后悔药(不能次日覆盖)
- 备份内容可验证(不能是空包)
- 系统崩了能快速重建
最终备份结构
/mnt/onedrive/bak/
├── Mon/ ← 周一备份(7天循环)
├── Tue/ ← 周二备份
├── Wed/ ← 周三备份
├── Thu/ ← 周四备份 ← 今天生成的
├── Fri/ ← 周五备份
├── Sat/ ← 周六备份
└── Sun/ ← 周日备份每个工作日目录内,包含以下备份文件:
Thu/
├── backup_server.sh ← 备份脚本本身(核心!)
├── crontab.txt ← Cron 任务配置导出
├── docker_volumes.tar.gz ← Docker 数据卷(待 Docker 可用后生效)
├── dockers.tar.gz ← /opt/dockers 容器配置
├── install_software.sh ← 快速安装脚本(可在新机跑)
├── nginx_conf.tar.gz ← Nginx conf.d 配置
├── nginx_ssl.tar.gz ← SSL 证书目录
├── openclaw.tar.gz ← OpenClaw 整个主目录
├── packages.txt ← 系统已装软件完整清单
├── service.tar.gz ← /opt/service 微服务
├── typecho.tar.gz ← 主博客(SQLite 安全打包)
└── typecho_sex.tar.gz ← 第二个博客单轮次总大小约 786M,7 天循环总共约 5.5G,对 OneDrive 来说毫无压力。
备份脚本核心设计
1. 按周轮替(而非次日覆盖)
WEEKDAY=$(date +%a) # Mon, Tue, Wed, Thu, Fri, Sat, Sun
WEEKDAY_DIR="${BACKUP_DIR}/${WEEKDAY}"每天备份写入对应星期目录,周一永远是周一的内容,不会被周二污染。即使今天数据损坏了,你还有 7 天的历史版本可以回滚。
2. 挂载点健康检测
check_mount() {
local test_file="${WEEKDAY_DIR}/.mount_health_check_$$"
if ! touch "${test_file}" 2>/dev/null; then
notify "❌" "挂载点不可写,备份中止"
exit 1
fi
rm -f "${test_file}"
}备份前先检测云盘挂载是否存活,挂了直接中止不往本地磁盘写,避免撑爆本地硬盘。
3. SQLite 热备份安全锁定
flush_sqlite() {
for pid in $(pgrep -f "php-fpm.*typecho"); do
kill -USR2 ${pid} 2>/dev/null
done
sleep 2 # 等待 WAL checkpoint 完成
}Typecho 使用 SQLite,直接 tar 打包正在写入的 .db 文件会损坏。打包前向 php-fpm 发送 USR2 信号刷新 WAL,然后等 2 秒再打包。
4. 备份完整性校验
verify_archive() {
local size=$(stat -c%s "${archive}")
if [ "${size}" -eq 0 ]; then return 1; fi
tar -tzf "${archive}" > /dev/null 2>&1 # 轻量校验:不解压,只列文件列表
}每个包打完都要过检,空包和损坏包会在通知里标 ❌,而不是伪装成成功。
5. 备份项清单(最终版)
| 备份项 | 路径 | 说明 |
|---|---|---|
| openclaw | /home/openclaw/ | OpenClaw 主目录,排除频繁变更的 session/json |
| typecho | /var/www/typecho/ | SQLite 数据库已做热备份锁定 |
| typecho_sex | /var/www/typecho_sex/ | 同上 |
| nginx_conf | /etc/nginx/conf.d/ | Nginx 站点配置 |
| nginx_ssl | /etc/nginx/ssl/ | SSL 证书(含 ECC 证书) |
| dockers | /opt/dockers/ | Docker Compose 配置 |
| service | /opt/service/ | Java/Python 微服务 |
| docker_volumes | /var/lib/docker/volumes/ | Docker 数据卷(需 Docker 可用) |
| backup_server.sh | 脚本自身 | 备份脚本自备份 |
| crontab.txt | cron -l 导出 | Cron 任务配置 |
| packages.txt | dpkg -l 导出 | 系统已装软件完整清单 |
| install_software.sh | 脚本生成 | 可在新机直接跑的一键安装脚本 |
权限踩坑全记录
sudoers 配置
Oracle 甲骨文 ARM 服务器默认没有 sudo 密码配置,OpenClaw 用 openclaw 用户运行,很多操作会被权限卡住。我在 /etc/sudoers.d/openclaw 里加了几类权限:
openclaw ALL=(ALL) NOPASSWD: /usr/bin/systemctl *
openclaw ALL=(ALL) NOPASSWD: /usr/bin/tar *
openclaw ALL=(ALL) NOPASSWD: /usr/bin/docker *
openclaw ALL=(ALL) NOPASSWD: /usr/bin/chmod 755 /root/.config/rclone/
openclaw ALL=(ALL) NOPASSWD: /usr/bin/cp /root/.config/rclone/rclone.conf *rclone.conf 权限问题
rclone 配置文件在 /root/.config/rclone/rclone.conf,权限结构是:
drwx------ root root /root/.config/
drwx------ root root /root/.config/rclone/
-rw-r----- root root rclone.conf即使把 rclone.conf 改成 644,目录本身的 x 权限也会拦住 openclaw 进不去。改 /root/.config/ 的权限会影响其他文件,不推荐。
最终解法:把 rclone.conf 复制到 openclaw 可达的地方:
sudo cp /root/.config/rclone/rclone.conf /home/openclaw/.openclaw/rclone.conf
sudo chmod 644 /home/openclaw/.openclaw/rclone.conf之后脚本从 /home/openclaw/.openclaw/rclone.conf 读,不动原始权限。
Telegram 通知效果
备份完成后的通知长这样:
✅ 服务器每日备份完成 [2026-05-28 Thu v4]
• openclaw: 160M
• typecho: 2.2M
• typecho_sex: 2.2M
• nginx_conf: 4.9K
• nginx_ssl: 46K
• dockers: 144M
• service: 474M
• backup_script: ✅
• packages.txt: 6.5K
• crontab.txt: 406B
💾 存放路径: OneDrive/bak/Thu/
⏰ 灾难缓冲期: 7 天每个备份项都有物理大小标注,空包一眼能看出来。
Cron 定时任务
# OpenClaw 定时任务(通过 cron API 注册)
name: 服务器每日备份
schedule: 0 2 * * * (Asia/Shanghai)
payload: agentTurn → bash /home/openclaw/.openclaw/backup_server.sh
delivery: announce → Telegram灾难恢复步骤(备忘)
如果某天系统彻底崩了,重建流程:
- 装系统 → Ubuntu 20.04 LTS
- 装软件 →
bash install_software.sh(在备份目录里) - 恢复配置 → 解压 nginx_conf.tar.gz、nginx_ssl.tar.gz
- 恢复数据 → 解压 openclaw.tar.gz、typecho.tar.gz、dockers.tar.gz、service.tar.gz
- 恢复脚本 → 解压 backup_server.sh,配置 cron
- 恢复包管理器 → 参考 packages.txt 补装软件
踩坑总结
- 不要次日同名覆盖,至少保留 7 天轮替,灾难缓冲是底线
- SQLite 数据库打包前要锁定,否则 WAL 会导致恢复失败
- 云盘挂载点要健康检测,假死时不能盲目写本地磁盘
- 每个备份包都要校验,空包和损坏包伪装成成功是最危险的
- 备份脚本自己也要备份,整个体系依赖它
- 软件包清单要每日同步,packages.txt 每次都生成最新版本
- root 目录权限慎重,用复制代替改权限
归档时间:2026-05-28 16:26 GMT+8
作者:Yala / OpenClaw AI 中台
当前备份体系版本:v4