Openclaw / sync-root-data.sh
Elysiadev11's picture
Update sync-root-data.sh
db492e1 verified
#!/usr/bin/env bash
set -euo pipefail
DATA_ROOT="${DATA_ROOT:-/data/root}"
SYNC_INTERVAL="${SYNC_INTERVAL:-300}"
CONFIG_PATH=".openclaw/openclaw.json"
EXCLUDES=(
"--exclude=.cache"
"--exclude=.npm/_cacache"
"--exclude=.npm/_update-notifier-last-checked*"
"--exclude=.pnpm-store"
"--exclude=node_modules"
"--exclude=.next"
"--exclude=dist"
"--exclude=build"
"--exclude=coverage"
"--exclude=tmp"
)
data_available() {
[ -d /data ] || mkdir -p /data 2>/dev/null || return 1
mkdir -p "$DATA_ROOT" 2>/dev/null || return 1
}
# /root → /data (--update: hanya file lebih baru di root yg masuk data)
persist_root() {
if data_available; then
echo "Syncing /root → $DATA_ROOT (update: root wins if newer)..."
rsync -rlptD --no-specials --no-devices --update --delete "${EXCLUDES[@]}" /root/ "$DATA_ROOT/" || true
else
echo "Persistent /data is not available; skipping persist."
fi
}
# /data → /root (FORCE: data selalu menang, tanpa --update)
restore_root() {
if data_available; then
echo "Restoring $DATA_ROOT → /root (force: data always wins)..."
rsync -rlptD --no-specials --no-devices "${EXCLUDES[@]}" "$DATA_ROOT/" /root/ || true
else
echo "Persistent /data is not available; skipping restore."
fi
}
sync_config_newer() {
local root_config="/root/$CONFIG_PATH"
local data_config="$DATA_ROOT/$CONFIG_PATH"
if [ -f "$data_config" ] && { [ ! -f "$root_config" ] || [ "$data_config" -nt "$root_config" ]; }; then
mkdir -p "$(dirname "$root_config")"
cp -p "$data_config" "$root_config" || true
echo "Pulled newer OpenClaw config: $data_config$root_config"
elif [ -f "$root_config" ] && { [ ! -f "$data_config" ] || [ "$root_config" -nt "$data_config" ]; }; then
mkdir -p "$(dirname "$data_config")"
cp -p "$root_config" "$data_config" || true
echo "Persisted newer OpenClaw config: $root_config$data_config"
fi
}
# Urutan penting:
# 1. persist → /root → /data (--update, perubahan root masuk data dulu)
# 2. config → two-way reconcile openclaw.json
# 3. restore → /data → /root (force, data selalu menang sebagai sumber kebenaran)
#
# Efeknya:
# - Root berubah → masuk data di step 1, restore step 3 no-op (sudah sama) ✓
# - Data berubah → step 1 tidak tumpuk data (--update), step 3 force ke root ✓
reconcile_root_data() {
if data_available; then
persist_root
sync_config_newer
restore_root
else
echo "Persistent /data is not available; skipping two-way sync."
fi
}
case "${1:-loop}" in
restore)
restore_root
;;
persist)
persist_root
;;
reconcile)
reconcile_root_data
;;
loop)
while true; do
reconcile_root_data
sleep "$SYNC_INTERVAL"
done
;;
*)
echo "Usage: $0 {restore|persist|reconcile|loop}"
exit 2
;;
esac