--- openclaw.sh +++ openclaw_patched.sh @@ -50,21 +50,21 @@ _ensure_brew &>/dev/null command -v brew &>/dev/null && brew install "$package" &>/dev/null elif command -v dnf &>/dev/null; then - dnf install -y "$package" &>/dev/null + run_root dnf install -y "$package" &>/dev/null elif command -v yum &>/dev/null; then - yum install -y "$package" &>/dev/null + run_root yum install -y "$package" &>/dev/null elif command -v apt &>/dev/null; then - DEBIAN_FRONTEND=noninteractive apt install -y "$package" &>/dev/null + run_root env DEBIAN_FRONTEND=noninteractive apt install -y "$package" &>/dev/null elif command -v apk &>/dev/null; then - apk add "$package" &>/dev/null + run_root apk add "$package" &>/dev/null elif command -v pacman &>/dev/null; then - pacman -S --noconfirm "$package" &>/dev/null + run_root pacman -S --noconfirm "$package" &>/dev/null elif command -v zypper &>/dev/null; then - zypper install -y "$package" &>/dev/null + run_root zypper install -y "$package" &>/dev/null elif command -v opkg &>/dev/null; then - opkg install "$package" &>/dev/null + run_root opkg install "$package" &>/dev/null elif command -v pkg &>/dev/null; then - pkg install -y "$package" &>/dev/null + run_root pkg install -y "$package" &>/dev/null else echo "未知的包管理器,无法安装 $package" return 1 @@ -76,6 +76,55 @@ is_macos() { [[ "$(uname -s)" == "Darwin" ]]; } +has_sudo_nopass() { + command -v sudo >/dev/null 2>&1 && sudo -n true >/dev/null 2>&1 +} + +run_root() { + if is_macos; then + "$@" + elif [[ "$EUID" -eq 0 ]]; then + "$@" + elif has_sudo_nopass; then + sudo "$@" + else + "$@" + fi +} + +run_root_sh() { + if is_macos; then + bash -lc "$*" + elif [[ "$EUID" -eq 0 ]]; then + bash -lc "$*" + elif has_sudo_nopass; then + sudo bash -lc "$*" + else + bash -lc "$*" + fi +} + +refresh_openclaw_path() { + hash -r 2>/dev/null || true + local candidates=() + local pfx usr_pfx + pfx=$(npm prefix -g 2>/dev/null || true) + [[ -n "$pfx" ]] && candidates+=("$pfx/bin") + if has_sudo_nopass; then + usr_pfx=$(sudo npm prefix -g 2>/dev/null || true) + [[ -n "$usr_pfx" ]] && candidates+=("$usr_pfx/bin") + fi + candidates+=(/usr/local/bin /usr/bin /opt/homebrew/bin "$HOME/.npm-global/bin") + local d + for d in "${candidates[@]}"; do + [[ -n "$d" && -x "$d/openclaw" ]] || continue + export PATH="$d:$PATH" + hash -r 2>/dev/null || true + return 0 + done + return 1 +} + _ensure_brew() { if ! command -v brew &>/dev/null; then if [[ -f /opt/homebrew/bin/brew ]]; then @@ -106,6 +155,57 @@ fi } + +set_openclaw_gateway_token() { + local config_file="${HOME}/.openclaw/openclaw.json" + [[ -f "$config_file" ]] || return 1 + command -v python3 >/dev/null 2>&1 || return 1 + python3 - "$config_file" <<'PYX' +import json, sys +path = sys.argv[1] +with open(path, 'r', encoding='utf-8') as f: + data = json.load(f) +gateway = data.setdefault('gateway', {}) +auth = gateway.setdefault('auth', {}) +auth['token'] = '123456' +with open(path, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + f.write('\n') +PYX +} + +apply_openclaw_post_install_config() { + local config_file="${HOME}/.openclaw/openclaw.json" + [[ -f "$config_file" ]] || return 1 + if command -v openclaw >/dev/null 2>&1; then + openclaw gateway stop >/dev/null 2>&1 || true + fi + _sed_i 's|"profile": "messaging"|"profile": "full"|g' "$config_file" + set_openclaw_gateway_token || return 1 + configure_openclaw_session_policy || true + if ! is_macos; then + systemctl --user enable openclaw-gateway.service 2>/dev/null || true + fi + start_gateway +} + +apply_cliproxy_post_install_config() { + local config_file; config_file=$(_cliproxy_conf) + [[ -f "$config_file" ]] || return 1 + _cliproxy_stop_service >/dev/null 2>&1 || true + command -v python3 >/dev/null 2>&1 || return 1 + python3 - "$config_file" <<'PYX' +import re, sys +path = sys.argv[1] +text = open(path, 'r', encoding='utf-8').read() +text = re.sub(r'(^\s*allow-remote:\s*).*$', r'\1true', text, flags=re.M) +text = re.sub(r'(^\s*secret-key:\s*).*$', r'\g<1>123456', text, flags=re.M) +with open(path, 'w', encoding='utf-8') as f: + f.write(text) +PYX + _cliproxy_start_service +} + install_base_deps() { if is_macos; then _ensure_brew || return 1 @@ -149,45 +249,45 @@ echo "正在安装缺失依赖:${missing_apt[*]}..." if command -v apt &>/dev/null; then - apt update -y &>/dev/null - DEBIAN_FRONTEND=noninteractive apt install -y "${missing_apt[@]}" &>/dev/null + run_root apt update -y &>/dev/null + run_root env DEBIAN_FRONTEND=noninteractive apt install -y "${missing_apt[@]}" &>/dev/null elif command -v dnf &>/dev/null; then - dnf install -y epel-release &>/dev/null || true - dnf install -y "${missing_dnf[@]}" &>/dev/null + run_root dnf install -y epel-release &>/dev/null || true + run_root dnf install -y "${missing_dnf[@]}" &>/dev/null elif command -v yum &>/dev/null; then - yum install -y epel-release &>/dev/null || true - yum install -y "${missing_dnf[@]}" &>/dev/null + run_root yum install -y epel-release &>/dev/null || true + run_root yum install -y "${missing_dnf[@]}" &>/dev/null elif command -v apk &>/dev/null; then - apk update &>/dev/null - apk add "${missing_apk[@]}" &>/dev/null + run_root apk update &>/dev/null + run_root apk add "${missing_apk[@]}" &>/dev/null elif command -v pacman &>/dev/null; then - pacman -Sy --noconfirm --needed "${missing_pacman[@]}" &>/dev/null + run_root pacman -Sy --noconfirm --needed "${missing_pacman[@]}" &>/dev/null elif command -v zypper &>/dev/null; then - zypper install -y "${missing_zypper[@]}" &>/dev/null + run_root zypper install -y "${missing_zypper[@]}" &>/dev/null fi if ! command -v python3 &>/dev/null; then local py py=$(compgen -c 2>/dev/null | grep -E '^python3\.[0-9]+$' | sort -V | tail -1) if [[ -n "$py" ]]; then - ln -sf "$(command -v "$py")" /usr/local/bin/python3 2>/dev/null || true + run_root ln -sf "$(command -v "$py")" /usr/local/bin/python3 2>/dev/null || true fi fi if ! command -v python3 &>/dev/null; then echo "正在安装 python3..." if command -v apt &>/dev/null; then - DEBIAN_FRONTEND=noninteractive apt install -y python3 &>/dev/null + run_root env DEBIAN_FRONTEND=noninteractive apt install -y python3 &>/dev/null elif command -v dnf &>/dev/null; then - dnf install -y python3 &>/dev/null + run_root dnf install -y python3 &>/dev/null elif command -v yum &>/dev/null; then - yum install -y python3 &>/dev/null + run_root yum install -y python3 &>/dev/null elif command -v apk &>/dev/null; then - apk add python3 &>/dev/null + run_root apk add python3 &>/dev/null elif command -v pacman &>/dev/null; then - pacman -S --noconfirm python &>/dev/null + run_root pacman -S --noconfirm python &>/dev/null elif command -v zypper &>/dev/null; then - zypper install -y python3 &>/dev/null + run_root zypper install -y python3 &>/dev/null fi hash -r 2>/dev/null || true fi @@ -210,7 +310,7 @@ tmp=$(mktemp -d) curl -fsSL "$url" -o "$tmp/gum.tar.gz" \ && tar -xzf "$tmp/gum.tar.gz" -C "$tmp" \ - && install -m 755 "$tmp/gum" /usr/local/bin/gum + && run_root install -m 755 "$tmp/gum" /usr/local/bin/gum rm -rf "$tmp" command -v gum >/dev/null 2>&1 } @@ -221,35 +321,35 @@ if command -v brew >/dev/null 2>&1; then brew install gum elif command -v apt >/dev/null 2>&1; then - command -v gpg >/dev/null 2>&1 || apt install -y gnupg 2>/dev/null - mkdir -p /etc/apt/keyrings + command -v gpg >/dev/null 2>&1 || run_root apt install -y gnupg 2>/dev/null + run_root mkdir -p /etc/apt/keyrings if curl -fsSL https://repo.charm.sh/apt/gpg.key \ - | gpg --dearmor -o /etc/apt/keyrings/charm.gpg 2>/dev/null; then + | run_root gpg --dearmor -o /etc/apt/keyrings/charm.gpg 2>/dev/null; then echo "deb [signed-by=/etc/apt/keyrings/charm.gpg] https://repo.charm.sh/apt/ * *" \ - | tee /etc/apt/sources.list.d/charm.list >/dev/null - apt update -y 2>/dev/null && apt install -y gum 2>/dev/null + | run_root tee /etc/apt/sources.list.d/charm.list >/dev/null + run_root apt update -y 2>/dev/null && run_root apt install -y gum 2>/dev/null fi command -v gum >/dev/null 2>&1 || _install_gum_binary elif command -v dnf &>/dev/null; then - cat > /etc/yum.repos.d/charm.repo <<'REPO' + run_root_sh "cat > /etc/yum.repos.d/charm.repo <<'REPO' [charm] name=Charm baseurl=https://repo.charm.sh/yum/ enabled=1 gpgcheck=1 gpgkey=https://repo.charm.sh/yum/gpg.key -REPO - dnf install -y gum +REPO" + run_root dnf install -y gum elif command -v yum &>/dev/null; then - cat > /etc/yum.repos.d/charm.repo <<'REPO' + run_root_sh "cat > /etc/yum.repos.d/charm.repo <<'REPO' [charm] name=Charm baseurl=https://repo.charm.sh/yum/ enabled=1 gpgcheck=1 gpgkey=https://repo.charm.sh/yum/gpg.key -REPO - yum install -y gum +REPO" + run_root yum install -y gum elif command -v apk &>/dev/null; then apk add gum 2>/dev/null || _install_gum_binary elif command -v pacman &>/dev/null; then @@ -268,17 +368,17 @@ if command -v brew >/dev/null 2>&1; then brew install fzf elif command -v apt >/dev/null 2>&1; then - apt install -y fzf + run_root apt install -y fzf elif command -v dnf &>/dev/null; then - dnf install -y fzf + run_root dnf install -y fzf elif command -v yum &>/dev/null; then - yum install -y fzf + run_root yum install -y fzf elif command -v apk &>/dev/null; then - apk add fzf + run_root apk add fzf elif command -v pacman &>/dev/null; then - pacman -S --noconfirm fzf + run_root pacman -S --noconfirm fzf elif command -v zypper &>/dev/null; then - zypper install -y fzf + run_root zypper install -y fzf else echo "无法自动安装 fzf,请手动安装: https://github.com/junegunn/fzf" return 1 @@ -410,11 +510,11 @@ _ensure_brew || return 1 brew install node &>/dev/null elif command -v dnf &>/dev/null; then - curl -fsSL https://rpm.nodesource.com/setup_24.x | bash - &>/dev/null - dnf install -y cmake libatomic nodejs &>/dev/null + curl -fsSL https://rpm.nodesource.com/setup_24.x | run_root bash - &>/dev/null + run_root dnf install -y cmake libatomic nodejs &>/dev/null elif command -v apt &>/dev/null; then - curl -fsSL https://deb.nodesource.com/setup_24.x | bash - &>/dev/null - DEBIAN_FRONTEND=noninteractive apt install -y build-essential python3 libatomic1 nodejs &>/dev/null + curl -fsSL https://deb.nodesource.com/setup_24.x | run_root bash - &>/dev/null + run_root env DEBIAN_FRONTEND=noninteractive apt install -y build-essential python3 libatomic1 nodejs &>/dev/null fi hash -r 2>/dev/null || true } @@ -765,11 +865,16 @@ if is_macos; then gum spin --spinner globe --title "正在安装 OpenClaw..." -- \ - env SHARP_IGNORE_GLOBAL_LIBVIPS=1 npm install -g openclaw@latest + bash -lc 'if command -v sudo >/dev/null 2>&1 && sudo -n true >/dev/null 2>&1; then sudo env SHARP_IGNORE_GLOBAL_LIBVIPS=1 npm install -g openclaw@latest; else env SHARP_IGNORE_GLOBAL_LIBVIPS=1 npm install -g openclaw@latest; fi' else - gum spin --spinner globe --title "正在安装 OpenClaw..." -- npm install -g openclaw@latest + gum spin --spinner globe --title "正在安装 OpenClaw..." -- bash -lc 'if command -v sudo >/dev/null 2>&1 && sudo -n true >/dev/null 2>&1; then sudo npm install -g openclaw@latest; else npm install -g openclaw@latest; fi' fi hash -r 2>/dev/null || true + if ! command -v openclaw >/dev/null 2>&1; then + for _bin in /usr/bin /usr/local/bin /opt/homebrew/bin; do + [[ -x "$_bin/openclaw" ]] && export PATH="$_bin:$PATH" + done + fi local npm_prefix npm_bin npm_prefix=$(npm prefix -g 2>/dev/null) npm_bin="${npm_prefix}/bin" @@ -782,12 +887,10 @@ done fi openclaw onboard --install-daemon - _sed_i 's|"profile": "messaging"|"profile": "full"|g' ~/.openclaw/openclaw.json - configure_openclaw_session_policy - if ! is_macos; then - systemctl --user enable openclaw-gateway.service 2>/dev/null || true - fi - start_gateway + apply_openclaw_post_install_config || { + ui_err "OpenClaw 安装后的配置写入失败,请检查 ~/.openclaw/openclaw.json" + return 1 + } } install_moltbot() { @@ -1238,6 +1341,11 @@ return 1 fi ui_ok "CLIProxyAPI 安装完成" + if ! apply_cliproxy_post_install_config; then + ui_err "CLIProxyAPI 配置写入失败,请检查 $cliproxy_config" + break_end + return 1 + fi ui_step "第 3 步:登录 AI 账号" ui_info "通过 OAuth 授权即可免费使用,无需付费 API Key" @@ -2199,7 +2307,7 @@ openclaw plugins enable "$plugin_id" else ui_warn "官方渠道下载失败,尝试 npm 备选方案..." - if npm install -g "$plugin_full" --unsafe-perm; then + if run_root npm install -g "$plugin_full" --unsafe-perm; then ui_ok "npm 安装成功,尝试启用..." openclaw plugins enable "$plugin_id" else @@ -3144,11 +3252,16 @@ install_node_and_tools if is_macos; then gum spin --spinner globe --title "正在更新 OpenClaw..." -- \ - env SHARP_IGNORE_GLOBAL_LIBVIPS=1 npm install -g openclaw@latest + bash -lc 'if command -v sudo >/dev/null 2>&1 && sudo -n true >/dev/null 2>&1; then sudo env SHARP_IGNORE_GLOBAL_LIBVIPS=1 npm install -g openclaw@latest; else env SHARP_IGNORE_GLOBAL_LIBVIPS=1 npm install -g openclaw@latest; fi' else - gum spin --spinner globe --title "正在更新 OpenClaw..." -- npm install -g openclaw@latest + gum spin --spinner globe --title "正在更新 OpenClaw..." -- bash -lc 'if command -v sudo >/dev/null 2>&1 && sudo -n true >/dev/null 2>&1; then sudo npm install -g openclaw@latest; else npm install -g openclaw@latest; fi' fi hash -r 2>/dev/null || true + if ! command -v openclaw >/dev/null 2>&1; then + for _bin in /usr/bin /usr/local/bin /opt/homebrew/bin; do + [[ -x "$_bin/openclaw" ]] && export PATH="$_bin:$PATH" + done + fi local npm_bin npm_bin="$(npm prefix -g 2>/dev/null)/bin" if [[ -n "$npm_bin" ]]; then @@ -3178,11 +3291,12 @@ gum spin --spinner meter --title "正在卸载 OpenClaw..." -- \ bash -c 'timeout 15 openclaw uninstall 2>/dev/null; true' - npm uninstall -g openclaw 2>/dev/null || true + run_root npm uninstall -g openclaw 2>/dev/null || true crontab -l 2>/dev/null | grep -v "s gateway" | crontab - 2>/dev/null || true rm -rf /root/.openclaw ~/.openclaw - rm -f "$HOME/.local/bin/oc" "$HOME/.local/bin/openclawctl.sh" /usr/local/bin/oc + rm -f "$HOME/.local/bin/oc" "$HOME/.local/bin/openclawctl.sh" 2>/dev/null || true + run_root rm -f /usr/local/bin/oc for rc in "$HOME/.zshrc" "$HOME/.bashrc" "$HOME/.profile"; do [[ -f "$rc" ]] || continue _sed_i '/\.local\/bin.*PATH/d' "$rc"