#!/usr/bin/env bash set -euo pipefail # Preserve HF Space variables (from os.environ) before sourcing env files # Priority: HF Space vars > env files _HF_SPACE_VARS=( "OPENCLAW_BACKUP_DATASET_REPO" "OPENCLAW_RESTORE_DATASET_REPO" "OPENCLAW_BACKUP_ENABLED" "OPENCLAW_BACKUP_NPM_ENABLED" "OPENCLAW_RESTORE_NPM_ENABLED" "OPENCLAW_VERSION" "HF_TOKEN" "HF_STORAGE_REPO" ) declare -A _PRESERVED_HF_VARS for _var in "${_HF_SPACE_VARS[@]}"; do if [[ -n "${!_var:-}" ]]; then _PRESERVED_HF_VARS["$_var"]="${!_var}" fi done # 恢复日志配置 RESTORE_LOG_DIR="${OPENCLAW_RESTORE_LOG_DIR:-/var/log/openclaw}" RESTORE_LOG_FILE="${RESTORE_LOG_DIR}/restore.log" # 确保日志目录存在 mkdir -p "$RESTORE_LOG_DIR" # 日志函数 restore_log() { local level="$1" shift local message="$*" local timestamp timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ") echo "[$timestamp] [$level] $message" | timeout 1 tee -a "$RESTORE_LOG_FILE" 2>/dev/null || echo "[$timestamp] [$level] $message" } restore_log_info() { restore_log "INFO" "$@" } restore_log_warn() { restore_log "WARN" "$@" } restore_log_error() { restore_log "ERROR" "$@" >&2 } restore_log_info "=== Starting Backup Restore ===" restore_log_info "Restore started at: $(date -u +"%Y-%m-%d %H:%M:%S UTC")" BACKUP_ENV_FILE_PATH="${OPENCLAW_BACKUP_ENV_FILE_PATH:-/root/.env.d/openclaw-backup.env}" if [[ -f "$BACKUP_ENV_FILE_PATH" ]]; then # shellcheck disable=SC1091 source "$BACKUP_ENV_FILE_PATH" restore_log_info "Loaded backup environment from: $BACKUP_ENV_FILE_PATH" else restore_log_warn "Backup environment file not found: $BACKUP_ENV_FILE_PATH" fi # Restore HF Space variables (they take priority over env files) for _var in "${!_PRESERVED_HF_VARS[@]}"; do export "$_var"="${_PRESERVED_HF_VARS[$_var]}" done unset _HF_SPACE_VARS _PRESERVED_HF_VARS _var # 记录恢复配置信息 restore_log_info "Restore Configuration:" # 多数据集支持:优先使用 OPENCLAW_RESTORE_DATASET_REPO,否则使用 OPENCLAW_BACKUP_DATASET_REPO RESTORE_DATASET_REPO="${OPENCLAW_RESTORE_DATASET_REPO:-${OPENCLAW_BACKUP_DATASET_REPO:-}}" if [[ -z "${RESTORE_DATASET_REPO:-}" ]]; then restore_log_warn "Restore skipped: no dataset configured" restore_log_warn " OPENCLAW_RESTORE_DATASET_REPO: ${OPENCLAW_RESTORE_DATASET_REPO:-}" restore_log_warn " OPENCLAW_BACKUP_DATASET_REPO: ${OPENCLAW_BACKUP_DATASET_REPO:-}" exit 2 fi restore_log_info " Restore Source Dataset: ${RESTORE_DATASET_REPO}" restore_log_info " Backup Dataset: ${OPENCLAW_BACKUP_DATASET_REPO:-}" restore_log_info " State Dir: ${OPENCLAW_STATE_DIR:-/root/.openclaw}" restore_log_info " Backup Source Dir: ${OPENCLAW_BACKUP_SOURCE_DIR:-}" restore_log_info " Path Prefix: ${OPENCLAW_BACKUP_PATH_PREFIX:-backups}" # 检查数据集配置 if [[ -z "${OPENCLAW_BACKUP_DATASET_REPO:-}" ]]; then restore_log_warn "Restore skipped: OPENCLAW_BACKUP_DATASET_REPO is not set" restore_log_warn "Backup target dataset is required for restore" exit 2 fi # 注意:容器重启/重建时总是执行恢复,这是设计决定的 restore_log_info "" restore_log_info "Starting restore process from dataset: ${RESTORE_DATASET_REPO}" restore_log_info "----------------------------------------" # Run restore with logging that won't block on disk full / write errors # Use a subshell to capture exit code independently of tee's exit status restore_exit_code=0 restore_output=$(python3 /opt/openclaw-hf/openclaw_hf/backup.py restore 2>&1) || restore_exit_code=$? # Write to log file without affecting restore result # If log file is not writable, we still want restore to succeed/fail based on actual result if ! echo "$restore_output" | tee -a "$RESTORE_LOG_FILE" >/dev/null 2>&1; then # Fallback: write to stderr if log file is not writable echo "$restore_output" >&2 restore_log_warn "Could not write to restore log file, output redirected to stderr" fi if [[ $restore_exit_code -eq 0 ]]; then restore_log_info "----------------------------------------" restore_log_info "=== Backup Restore Completed Successfully ===" restore_log_info "Restore source: ${RESTORE_DATASET_REPO}" restore_log_info "Restore finished at: $(date -u +"%Y-%m-%d %H:%M:%S UTC")" exit 0 else restore_log_error "----------------------------------------" restore_log_error "=== Backup Restore Failed ===" restore_log_error "Restore source: ${RESTORE_DATASET_REPO}" restore_log_error "Restore failed at: $(date -u +"%Y-%m-%d %H:%M:%S UTC")" exit 1 fi