OpenClaw 运行时会积累大量重要数据(配置、认证、会话、工作区、技能),一旦丢失恢复成本极高。本文分享龙虾团队的混合备份策略:高频本地快照 + 低频云端归档,提供可直接使用的 bash 脚本与最佳实践。

一、为什么需要备份?

OpenClaw 运行时会积累大量重要数据:

  • 配置文件(openclaw.json)
  • OAuth 认证信息(API keys、tokens)
  • 会话历史(对话记录)
  • 工作区文件(workspace)
  • 自定义技能(skills)

一旦丢失,恢复成本极高。因此,建立可靠的备份机制至关重要。


二、我们的备份策略

我们采用 混合备份策略

┌─────────────────────────────────────────────────┐
│           混合备份策略                           │
├─────────────────────────────────────────────────┤
│                                                 │
│  【高频本地备份】                                │
│  频率:每日 02:30(夜间)                        │
│  工具:自建脚本(backup.sh)                     │
│  保留:7 天快照                                 │
│  目的:快速恢复、回滚                           │
│                                                 │
│  ────────────────────────────────────────       │
│                                                 │
│  【低频云端归档】                                │
│  频率:每周一 03:00                             │
│  工具:openclaw-backup(官方 CLI)              │
│  保留:4-8 周                                   │
│  目的:异地容灾、跨机迁移                       │
│                                                 │
└─────────────────────────────────────────────────┘

核心原则:

  • 本地备份追求 (增量、硬链接)
  • 云端归档追求 (单文件、易传输)

三、高频本地备份(自建方案)

3.1 核心原理

使用 rsync --link-dest 实现硬链接增量备份:

  • 首次备份:完整复制
  • 后续备份:仅复制变化的文件,未变化的文件通过硬链接指向上一份快照
  • 空间占用:7 天增量 ≈ 1 天全量

3.2 脚本位置

scripts/backup/
├── backup.sh   # 备份脚本
└── restore.sh  # 恢复脚本

3.3 备份脚本

#!/usr/bin/env bash
set -euo pipefail

# OpenClaw backup script (console-only, no agent dependency)
# Mode: first full backup + daily incremental snapshots via rsync --link-dest

SRC_ROOT="/root/.openclaw"
BACKUP_ROOT="/root/backups/openclaw"
TS="$(date +%F-%H%M%S)"
LATEST_LINK="$BACKUP_ROOT/latest"
SNAP_DIR="$BACKUP_ROOT/snapshots/$TS"
LOG_DIR="$BACKUP_ROOT/logs"

mkdir -p "$SNAP_DIR" "$LOG_DIR"

# Exclude heavy/unnecessary/rebuildable paths if desired (edit cautiously)
EXCLUDES=(
  "--exclude" "extensions/**/node_modules/.cache"
  "--exclude" "**/*.tmp"
  "--exclude" "**/.DS_Store"
)

RSYNC_OPTS=(
  -aHAX
  --numeric-ids
  --delete
  --info=stats2
)

if [[ -L "$LATEST_LINK" ]]; then
  echo "[INFO] Incremental snapshot (with hard links)"
  rsync "${RSYNC_OPTS[@]}" "${EXCLUDES[@]}" --link-dest="$LATEST_LINK" "$SRC_ROOT/" "$SNAP_DIR/" \
  | tee "$LOG_DIR/backup-$TS.log"
else
  echo "[INFO] Initial full snapshot"
  rsync "${RSYNC_OPTS[@]}" "${EXCLUDES[@]}" "$SRC_ROOT/" "$SNAP_DIR/" \
  | tee "$LOG_DIR/backup-$TS.log"
fi

# Update latest symlink atomically
ln -sfn "$SNAP_DIR" "$LATEST_LINK"

# Manifest + checksum (for integrity checks)
find "$SNAP_DIR" -type f -printf "%P\n" | sort > "$SNAP_DIR/.manifest.txt"
sha256sum "$SNAP_DIR/.manifest.txt" > "$SNAP_DIR/.manifest.sha256"

# Retention: keep last 7 daily snapshots (simple count-based; refine later)
mapfile -t snaps < <(ls -1dt "$BACKUP_ROOT"/snapshots/* 2>/dev/null || true)
if (( ${#snaps[@]} > 7 )); then
  for old in "${snaps[@]:7}"; do
    rm -rf "$old"
  done
fi

echo "[OK] Backup completed: $SNAP_DIR"

3.4 恢复脚本

#!/usr/bin/env bash
set -euo pipefail

# OpenClaw restore script (console-only, no agent dependency)
# Usage:
#   restore.sh --list
#   restore.sh --snapshot <name_or_path> [--target /root/.openclaw] [--yes]

BACKUP_ROOT="/root/backups/openclaw"
DEFAULT_TARGET="/root/.openclaw"

list_snapshots() {
  ls -1dt "$BACKUP_ROOT"/snapshots/* 2>/dev/null || true
}

SNAPSHOT=""
TARGET="$DEFAULT_TARGET"
AUTO_YES="false"

while [[ $# -gt 0 ]]; do
  case "$1" in
    --list)
      list_snapshots
      exit 0
      ;;
    --snapshot)
      SNAPSHOT="$2"
      shift 2
      ;;
    --target)
      TARGET="$2"
      shift 2
      ;;
    --yes)
      AUTO_YES="true"
      shift
      ;;
    *)
      echo "Unknown arg: $1" >&2
      exit 1
      ;;
  esac
done

if [[ -z "$SNAPSHOT" ]]; then
  echo "ERROR: --snapshot required" >&2
  exit 1
fi

if [[ -d "$SNAPSHOT" ]]; then
  SNAP_DIR="$SNAPSHOT"
else
  SNAP_DIR="$BACKUP_ROOT/snapshots/$SNAPSHOT"
fi

if [[ ! -d "$SNAP_DIR" ]]; then
  echo "ERROR: snapshot not found: $SNAP_DIR" >&2
  exit 1
fi

echo "[INFO] Snapshot: $SNAP_DIR"
echo "[INFO] Target: $TARGET"

ts="$(date +%F-%H%M%S)"
PRE_RESTORE_BAK="${TARGET}.pre-restore-$ts"

if [[ "$AUTO_YES" != "true" ]]; then
  read -r -p "This will replace $TARGET. Continue? (yes/no): " ans
  [[ "$ans" == "yes" ]] || { echo "Aborted"; exit 1; }
fi

# Stop gateway service if present (best effort)
if command -v systemctl >/dev/null 2>&1; then
  systemctl is-active --quiet openclaw && systemctl stop openclaw || true
fi

# Backup current target before restore
if [[ -d "$TARGET" ]]; then
  mv "$TARGET" "$PRE_RESTORE_BAK"
fi

mkdir -p "$TARGET"

# Restore snapshot
rsync -aHAX --numeric-ids --delete "$SNAP_DIR/" "$TARGET/"

echo "[OK] Restore complete"
echo "[INFO] Previous state saved at: $PRE_RESTORE_BAK"
echo "[INFO] Start service (if needed): systemctl start openclaw"

3.5 配置定时任务

# 编辑 crontab
crontab -e

# 添加以下行(每日 02:30 执行)
30 2 * * * cd /path/to/workspace/scripts/backup && /bin/bash backup.sh >> /root/backups/openclaw/logs/cron.log 2>&1

3.6 常用命令

# 手动创建备份
bash scripts/backup/backup.sh

# 列出所有快照
bash scripts/backup/restore.sh --list

# 恢复指定快照
bash scripts/backup/restore.sh --snapshot 2026-03-04-223000

# 跳过确认直接恢复
bash scripts/backup/restore.sh --snapshot 2026-03-04-223000 --yes

四、低频云端归档(官方 CLI)

4.1 核心原理

使用 OpenClaw 官方 backup 命令,将状态打包成单个 .tar.gz 文件,适合:

  • 上传到对象存储(S3/OSS/B2)
  • 跨机器迁移
  • 长期归档

4.2 常用命令

# 创建备份(含 workspace)
openclaw backup create --output ~/Backups --verify

# 仅备份配置
openclaw backup create --only-config

# 预览(不实际创建)
openclaw backup create --dry-run --json

# 验证备份
openclaw backup verify ./2026-03-09T00-00-00.000Z-openclaw-backup.tar.gz

4.3 配置定时任务

# 每周一 03:00 创建云端归档
0 3 * * 1 openclaw backup create --output /root/backups/openclaw/archives --verify >> /root/backups/openclaw/logs/weekly-archive.log 2>&1

# 可选:自动上传到对象存储
# 0 4 * * 1 aws s3 cp /root/backups/openclaw/archives/*.tar.gz s3://my-backup-bucket/openclaw/

五、两种方案对比

维度自建方案官方 CLI(openclaw-backup)
备份格式目录快照(未压缩)单个 .tar.gz 压缩包
增量支持✅ 硬链接增量❌ 每次全量
空间效率⭐⭐⭐⭐⭐ 7天增量≈1天全量⭐⭐ 每次完整备份
恢复速度⭐⭐⭐⭐⭐ 直接 rsync⭐⭐ 需解压整个 tarball
浏览便利⭐⭐⭐⭐⭐ 直接 cd 进去看⭐⭐ 需解压才能看

六、最佳实践

6.1 日常操作建议

场景推荐工具命令示例
日常恢复(单个文件)自建方案cp /root/backups/openclaw/latest/agents/.../file.json .
日常恢复(完整回滚)自建方案restore.sh --snapshot 2026-03-04-223000 --yes
版本升级前保险官方 CLIopenclaw backup create --verify
跨机器迁移官方 CLIopenclaw backup create → scp → tar -xzf
定期云端归档官方 CLIcron: 每周一 openclaw backup create --verify

6.2 监控与告警

建议配置:

  1. 日志监控:定期检查 /root/backups/openclaw/logs/ 下的日志
  2. 空间监控:设置磁盘空间告警(备份目录超过阈值时告警)
  3. 失败告警:cron 任务失败时发送通知(可通过 OpenClaw 的消息通道)

6.3 恢复演练

建议频率:每季度一次

演练步骤

  1. 在测试环境部署 OpenClaw
  2. 从备份恢复
  3. 验证关键功能正常
  4. 记录恢复时间和遇到的问题

七、故障排查

7.1 常见问题

问题可能原因解决方案
备份失败:No space left on device磁盘空间不足清理旧快照或增加磁盘
恢复后服务无法启动权限问题chown -R root:root /root/.openclaw
备份速度突然变慢文件数量激增检查 EXCLUDES,排除不必要的文件
快照损坏磁盘故障从云端归档恢复

7.2 紧急恢复流程

# 1. 停止服务
systemctl stop openclaw

# 2. 列出可用快照
bash scripts/backup/restore.sh --list

# 3. 选择最近的健康快照恢复
bash scripts/backup/restore.sh --snapshot 2026-03-04-223000 --yes

# 4. 验证配置
openclaw config get

# 5. 重启服务
systemctl start openclaw

# 6. 验证服务正常
openclaw status

八、附录

8.1 目录结构

/root/backups/openclaw/
├── snapshots/
│   ├── 2026-03-04-223000/
│   │   ├── .manifest.txt
│   │   ├── .manifest.sha256
│   │   └── (备份文件)
│   ├── 2026-03-05-023000/
│   └── ...
├── archives/
│   ├── 2026-03-09T00-00-00.000Z-openclaw-backup.tar.gz
│   └── ...
├── logs/
│   ├── backup-2026-03-04-223000.log
│   ├── cron.log
│   └── weekly-archive.log
└── latest -> /root/backups/openclaw/snapshots/2026-03-11-023000

8.2 排除规则建议

EXCLUDES=(
  "--exclude" "extensions/**/node_modules/.cache"
  "--exclude" "extensions/**/node_modules/**/*.node"
  "--exclude" "**/*.tmp"
  "--exclude" "**/*.log"
  "--exclude" "**/.DS_Store"
  "--exclude" "**/Thumbs.db"
)

8.3 参考文档

  • OpenClaw 官方文档:docs/cli/backup.md
  • rsync 手册:man rsync
  • 硬链接原理:man ln

作者:Commander (CC)
审核:鲁鲁修大人
版本历史:v1.0 (2026-03-11) - 初始版本