Initial commit: OpenClaw ops workspace
This commit is contained in:
125
scripts/backup-openclaw-state.sh
Executable file
125
scripts/backup-openclaw-state.sh
Executable file
@@ -0,0 +1,125 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Backs up key OpenClaw state to a versioned ZIP archive.
|
||||
# Includes:
|
||||
# - ~/.openclaw/openclaw.json
|
||||
# - ~/.openclaw/cron/
|
||||
# - ~/.openclaw/credentials/
|
||||
# - ~/.openclaw/delivery-queue/ (if present)
|
||||
#
|
||||
# Usage:
|
||||
# scripts/backup-openclaw-state.sh [output_dir]
|
||||
# Example:
|
||||
# scripts/backup-openclaw-state.sh /home/node/.openclaw/backups
|
||||
|
||||
OPENCLAW_HOME="${OPENCLAW_HOME:-$HOME/.openclaw}"
|
||||
OUTPUT_DIR="${1:-$OPENCLAW_HOME/backups}"
|
||||
TS="$(date -u +"%Y%m%d-%H%M%SZ")"
|
||||
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
get_version() {
|
||||
local raw ver
|
||||
raw="$(openclaw --version 2>/dev/null || true)"
|
||||
if [[ -n "$raw" ]]; then
|
||||
ver="$(printf '%s' "$raw" | head -n1 | sed -E 's/[^0-9A-Za-z._-]+/-/g; s/^-+|-+$//g')"
|
||||
if [[ -n "$ver" ]]; then
|
||||
printf '%s' "$ver"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
raw="$(openclaw status 2>/dev/null | grep -E 'Channel|Update' | head -n1 || true)"
|
||||
ver="$(printf '%s' "$raw" | sed -E 's/[^0-9A-Za-z._-]+/-/g; s/^-+|-+$//g')"
|
||||
if [[ -n "$ver" ]]; then
|
||||
printf '%s' "$ver"
|
||||
else
|
||||
printf 'unknown'
|
||||
fi
|
||||
}
|
||||
|
||||
VERSION="$(get_version)"
|
||||
ARCHIVE_NAME="openclaw-backup-${TS}-v${VERSION}.zip"
|
||||
ARCHIVE_PATH="$OUTPUT_DIR/$ARCHIVE_NAME"
|
||||
|
||||
# Build include list (required + optional)
|
||||
INCLUDE_PATHS=()
|
||||
|
||||
if [[ -f "$OPENCLAW_HOME/openclaw.json" ]]; then
|
||||
INCLUDE_PATHS+=("$OPENCLAW_HOME/openclaw.json")
|
||||
else
|
||||
echo "WARN: Missing $OPENCLAW_HOME/openclaw.json" >&2
|
||||
fi
|
||||
|
||||
if [[ -d "$OPENCLAW_HOME/cron" ]]; then
|
||||
INCLUDE_PATHS+=("$OPENCLAW_HOME/cron")
|
||||
else
|
||||
echo "WARN: Missing $OPENCLAW_HOME/cron" >&2
|
||||
fi
|
||||
|
||||
if [[ -d "$OPENCLAW_HOME/credentials" ]]; then
|
||||
INCLUDE_PATHS+=("$OPENCLAW_HOME/credentials")
|
||||
else
|
||||
echo "WARN: Missing $OPENCLAW_HOME/credentials" >&2
|
||||
fi
|
||||
|
||||
if [[ -d "$OPENCLAW_HOME/delivery-queue" ]]; then
|
||||
INCLUDE_PATHS+=("$OPENCLAW_HOME/delivery-queue")
|
||||
fi
|
||||
|
||||
if [[ ${#INCLUDE_PATHS[@]} -eq 0 ]]; then
|
||||
echo "ERROR: Nothing to back up." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create a temp metadata file and include it in the archive.
|
||||
TMP_DIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$TMP_DIR"' EXIT
|
||||
META_FILE="$TMP_DIR/backup-metadata.txt"
|
||||
|
||||
{
|
||||
echo "timestamp_utc=$TS"
|
||||
echo "openclaw_version=$VERSION"
|
||||
echo "openclaw_home=$OPENCLAW_HOME"
|
||||
echo "archive_name=$ARCHIVE_NAME"
|
||||
echo "included_paths="
|
||||
for p in "${INCLUDE_PATHS[@]}"; do
|
||||
echo " - $p"
|
||||
done
|
||||
} > "$META_FILE"
|
||||
|
||||
# Create zip via Python for consistent behavior.
|
||||
python3 - "$ARCHIVE_PATH" "$META_FILE" "${INCLUDE_PATHS[@]}" <<'PY'
|
||||
import os
|
||||
import sys
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
archive = Path(sys.argv[1])
|
||||
meta_file = Path(sys.argv[2])
|
||||
items = [Path(p) for p in sys.argv[3:]]
|
||||
|
||||
with zipfile.ZipFile(archive, "w", compression=zipfile.ZIP_DEFLATED) as zf:
|
||||
# Put metadata at archive root
|
||||
zf.write(meta_file, arcname="backup-metadata.txt")
|
||||
|
||||
for item in items:
|
||||
if not item.exists():
|
||||
continue
|
||||
|
||||
if item.is_file():
|
||||
zf.write(item, arcname=str(item).lstrip("/"))
|
||||
else:
|
||||
for root, dirs, files in os.walk(item):
|
||||
root_path = Path(root)
|
||||
# preserve empty dirs
|
||||
if not files and not dirs:
|
||||
zi = zipfile.ZipInfo(str(root_path).lstrip("/") + "/")
|
||||
zf.writestr(zi, "")
|
||||
for f in files:
|
||||
fp = root_path / f
|
||||
zf.write(fp, arcname=str(fp).lstrip("/"))
|
||||
PY
|
||||
|
||||
echo "Backup created: $ARCHIVE_PATH"
|
||||
Reference in New Issue
Block a user