| #!/usr/bin/env bash |
| set -euo pipefail |
|
|
| OPENCLAW_ENTRYPOINT_TAG="upgrade-openclaw" |
|
|
| timestamp_utc() { |
| date -u +"%Y-%m-%dT%H:%M:%SZ" |
| } |
|
|
| log_info() { |
| printf '[%s] [INFO] [%s] %s\n' "$(timestamp_utc)" "$OPENCLAW_ENTRYPOINT_TAG" "$*" |
| } |
|
|
| log_warn() { |
| printf '[%s] [WARN] [%s] %s\n' "$(timestamp_utc)" "$OPENCLAW_ENTRYPOINT_TAG" "$*" >&2 |
| } |
|
|
| log_error() { |
| printf '[%s] [ERROR] [%s] %s\n' "$(timestamp_utc)" "$OPENCLAW_ENTRYPOINT_TAG" "$*" >&2 |
| } |
|
|
| is_true() { |
| local value |
| value="$(printf '%s' "${1:-}" | tr '[:upper:]' '[:lower:]')" |
| [[ "$value" == "1" || "$value" == "true" || "$value" == "yes" || "$value" == "on" ]] |
| } |
|
|
| get_current_version() { |
| local version |
| if command -v openclaw >/dev/null 2>&1; then |
| version="$(openclaw --version 2>/dev/null | head -1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)" || version="" |
| if [[ -z "$version" ]]; then |
| version="$(openclaw --version 2>/dev/null | head -1 | awk '{print $NF}')" || version="unknown" |
| fi |
| else |
| version="not-installed" |
| fi |
| printf '%s' "$version" |
| } |
|
|
| resolve_latest_version() { |
| local version |
| version="$(curl -fsSL https://registry.npmjs.org/openclaw/latest 2>/dev/null | python3 -c " |
| import json, sys |
| try: |
| data = json.load(sys.stdin) |
| print(data.get('version', 'latest')) |
| except: |
| print('latest') |
| " 2>/dev/null)" || version="latest" |
| printf '%s' "$version" |
| } |
|
|
| backup_openclaw_state() { |
| local backup_dir="/root/.openclaw.backup.$(date +%Y%m%d%H%M%S)" |
| |
| if [[ -d "/root/.openclaw" ]]; then |
| log_info "Backing up OpenClaw state to $backup_dir..." |
| cp -r /root/.openclaw "$backup_dir" |
| log_info "Backup completed: $backup_dir" |
| else |
| log_warn "No existing OpenClaw state found, skipping backup" |
| fi |
| } |
|
|
| upgrade_openclaw() { |
| local target_version="$1" |
| local skip_backup="$2" |
| |
| if ! is_true "$skip_backup"; then |
| backup_openclaw_state |
| fi |
| |
| log_info "Upgrading OpenClaw to version: $target_version..." |
| |
| local install_start |
| install_start=$(date +%s) |
| |
| HOME=/root curl -fsSL https://openclaw.ai/install.sh | bash -s -- --no-onboard --version "$target_version" |
| |
| local install_end |
| install_end=$(date +%s) |
| local install_duration=$((install_end - install_start)) |
| |
| log_info "Installation completed in ${install_duration}s" |
| |
| local new_version |
| new_version="$(get_current_version)" |
| log_info "OpenClaw upgraded to: $new_version" |
| |
| if [[ "$new_version" == "unknown" || "$new_version" == "not-installed" ]]; then |
| log_error "Upgrade verification failed: openclaw command not found" |
| return 1 |
| fi |
| |
| if [[ "$target_version" != "latest" && "$new_version" != *"$target_version"* ]]; then |
| log_warn "Version mismatch: expected $target_version, got $new_version" |
| fi |
| |
| return 0 |
| } |
|
|
| restart_gateway() { |
| log_info "Restarting OpenClaw gateway..." |
| |
| if command -v openclaw-gateway-ctl >/dev/null 2>&1; then |
| if openclaw-gateway-ctl status >/dev/null 2>&1; then |
| openclaw-gateway-ctl restart || log_warn "Gateway restart failed, manual restart may be needed" |
| else |
| log_warn "Gateway is not running, skipping restart" |
| fi |
| else |
| log_warn "openclaw-gateway-ctl not found, skipping gateway restart" |
| fi |
| } |
|
|
| show_usage() { |
| cat <<'EOF' |
| Usage: upgrade-openclaw.sh [OPTIONS] [VERSION] |
|
|
| Upgrade OpenClaw to a specific version or the latest version. |
|
|
| Arguments: |
| VERSION Target version (default: from OPENCLAW_VERSION env var, or "latest") |
|
|
| Options: |
| -l, --latest Upgrade to the latest version |
| -v, --version VER Specify version to upgrade to |
| -s, --skip-backup Skip backup of current state |
| -n, --dry-run Show what would be done without making changes |
| -h, --help Show this help message |
|
|
| Environment Variables: |
| OPENCLAW_VERSION Target version (overridden by command line arguments) |
|
|
| Examples: |
| upgrade-openclaw.sh |
| upgrade-openclaw.sh 2026.5.1 |
| upgrade-openclaw.sh --latest |
| upgrade-openclaw.sh -v 2026.4.15 -s |
| upgrade-openclaw.sh --dry-run |
| EOF |
| } |
|
|
| main() { |
| local target_version="" |
| local skip_backup="false" |
| local dry_run="false" |
| local use_latest="false" |
| |
| while [[ $# -gt 0 ]]; do |
| case "$1" in |
| -l|--latest) |
| use_latest="true" |
| shift |
| ;; |
| -v|--version) |
| target_version="$2" |
| shift 2 |
| ;; |
| -s|--skip-backup) |
| skip_backup="true" |
| shift |
| ;; |
| -n|--dry-run) |
| dry_run="true" |
| shift |
| ;; |
| -h|--help) |
| show_usage |
| exit 0 |
| ;; |
| -*) |
| log_error "Unknown option: $1" |
| show_usage |
| exit 1 |
| ;; |
| *) |
| target_version="$1" |
| shift |
| ;; |
| esac |
| done |
| |
| if [[ -z "$target_version" ]]; then |
| if is_true "$use_latest"; then |
| target_version="latest" |
| elif [[ -n "${OPENCLAW_VERSION:-}" ]]; then |
| target_version="$OPENCLAW_VERSION" |
| else |
| target_version="latest" |
| fi |
| fi |
| |
| local current_version |
| current_version="$(get_current_version)" |
| |
| log_info "==========================================" |
| log_info "OpenClaw Upgrade Tool" |
| log_info "==========================================" |
| log_info "Current version: $current_version" |
| log_info "Target version: $target_version" |
| log_info "Skip backup: $skip_backup" |
| log_info "Dry run: $dry_run" |
| log_info "==========================================" |
| |
| if [[ "$current_version" == "$target_version" ]] || [[ "$current_version" == *"$target_version"* && "$target_version" != "latest" ]]; then |
| log_info "Already at target version, no upgrade needed" |
| exit 0 |
| fi |
| |
| if is_true "$dry_run"; then |
| log_info "[DRY RUN] Would upgrade OpenClaw from $current_version to $target_version" |
| if ! is_true "$skip_backup"; then |
| log_info "[DRY RUN] Would backup current state to /root/.openclaw.backup.<timestamp>" |
| fi |
| log_info "[DRY RUN] Would restart gateway after upgrade" |
| exit 0 |
| fi |
| |
| if [[ "$target_version" == "latest" ]]; then |
| local resolved_version |
| resolved_version="$(resolve_latest_version)" |
| log_info "Resolved 'latest' to: $resolved_version" |
| |
| if [[ "$current_version" == "$resolved_version" ]] || [[ "$current_version" == *"$resolved_version"* ]]; then |
| log_info "Already at latest version ($resolved_version), no upgrade needed" |
| exit 0 |
| fi |
| |
| target_version="$resolved_version" |
| fi |
| |
| upgrade_openclaw "$target_version" "$skip_backup" |
| |
| log_info "Upgrade completed successfully" |
| log_info "New version: $(get_current_version)" |
| |
| restart_gateway |
| |
| log_info "==========================================" |
| log_info "Upgrade finished!" |
| log_info "==========================================" |
| } |
|
|
| main "$@" |
|
|