#!/bin/bash # ============================================================ # U-Claw - Install to Linux (从 U 盘安装到电脑) # 优先使用 U 盘内的离线资源,缺失时从国内镜像下载 # ============================================================ set -e UCLAW_DIR="$(cd "$(dirname "$0")" && pwd)" APP_DIR="$UCLAW_DIR/app" INSTALL_TARGET="$HOME/.uclaw" GREEN='\033[0;32m' CYAN='\033[0;36m' RED='\033[0;31m' YELLOW='\033[1;33m' NC='\033[0m' BOLD='\033[1m' DIM='\033[2m' NODE_VER="v22.14.0" MIRROR="https://registry.npmmirror.com" NODE_MIRROR="https://npmmirror.com/mirrors/node" clear echo "" echo -e "${CYAN}${BOLD}" echo " ╔══════════════════════════════════════╗" echo " ║ U-Claw 安装到 Linux ║" echo " ║ 从 U 盘离线安装 ║" echo " ╚══════════════════════════════════════╝" echo -e "${NC}" echo "" # ---- Check CPU ---- ARCH=$(uname -m) if [ "$ARCH" = "x86_64" ]; then echo -e " ${GREEN}Linux x86_64 ✓${NC}" NODE_PLATFORM="node-linux-x64" elif [ "$ARCH" = "aarch64" ]; then echo -e " ${GREEN}Linux ARM64 ✓${NC}" NODE_PLATFORM="node-linux-arm64" else echo -e " ${RED}Unsupported architecture: $ARCH${NC}" exit 1 fi echo "" # ---- Check existing installation ---- if [ -d "$INSTALL_TARGET" ]; then echo -e " ${YELLOW}检测到已有安装: $INSTALL_TARGET${NC}" read -p " 覆盖安装?(y/n): " -n 1 OVERWRITE echo "" if [ "$OVERWRITE" != "y" ] && [ "$OVERWRITE" != "Y" ]; then echo -e " ${DIM}已取消${NC}" exit 0 fi echo "" fi # ---- Step 1: Check environment ---- echo -e " ${BOLD}[1/4] 检查环境...${NC}" NEED_DOWNLOAD_NODE=false NEED_DOWNLOAD_OPENCLAW=false # Check Node.js - prefer USB, then system, then download USB_NODE="$APP_DIR/runtime/$NODE_PLATFORM/bin/node" USB_NPM="$APP_DIR/runtime/$NODE_PLATFORM/bin/npm" if [ -f "$USB_NODE" ]; then echo -e " ${GREEN}Node.js: 使用 U 盘内的 ($("$USB_NODE" --version))${NC}" USE_NODE="usb" elif command -v node >/dev/null 2>&1; then SYS_VER=$(node --version) MAJOR=$(echo "$SYS_VER" | sed 's/v//' | cut -d. -f1) if [ "$MAJOR" -ge 20 ] 2>/dev/null; then echo -e " ${GREEN}Node.js: 使用系统的 ($SYS_VER)${NC}" USE_NODE="system" else echo -e " ${YELLOW}Node.js: 系统版本太低 ($SYS_VER),需要 v20+${NC}" NEED_DOWNLOAD_NODE=true USE_NODE="download" fi else echo -e " ${YELLOW}Node.js: 未安装${NC}" NEED_DOWNLOAD_NODE=true USE_NODE="download" fi # Check OpenClaw USB_OPENCLAW="$APP_DIR/core/node_modules/openclaw/openclaw.mjs" if [ -f "$USB_OPENCLAW" ]; then echo -e " ${GREEN}OpenClaw: 使用 U 盘内的${NC}" USE_OPENCLAW="usb" else echo -e " ${YELLOW}OpenClaw: U 盘内未找到,需要在线下载${NC}" NEED_DOWNLOAD_OPENCLAW=true USE_OPENCLAW="download" fi echo "" # ---- Step 2: Create install directory ---- echo -e " ${BOLD}[2/4] 安装到 $INSTALL_TARGET ...${NC}" mkdir -p "$INSTALL_TARGET" mkdir -p "$INSTALL_TARGET/data/.openclaw" mkdir -p "$INSTALL_TARGET/data/memory" mkdir -p "$INSTALL_TARGET/data/backups" # ---- Step 3: Copy/Download Node.js ---- echo -e " ${BOLD}[3/4] 安装 Node.js...${NC}" NODE_INSTALL_DIR="$INSTALL_TARGET/runtime/$NODE_PLATFORM" case $USE_NODE in usb) echo -e " ${CYAN}从 U 盘复制 Node.js...${NC}" mkdir -p "$NODE_INSTALL_DIR" cp -R "$APP_DIR/runtime/$NODE_PLATFORM/"* "$NODE_INSTALL_DIR/" chmod +x "$NODE_INSTALL_DIR/bin/node" INSTALL_NODE="$NODE_INSTALL_DIR/bin/node" INSTALL_NPM="$NODE_INSTALL_DIR/bin/npm" echo -e " ${GREEN}Node.js 安装完成 ✓${NC}" ;; system) INSTALL_NODE="$(which node)" INSTALL_NPM="$(which npm)" echo -e " ${GREEN}使用系统 Node.js ✓${NC}" ;; download) echo -e " ${CYAN}从国内镜像下载 Node.js $NODE_VER...${NC}" PLATFORM_NAME="linux-$( [ "$ARCH" = "x86_64" ] && echo "x64" || echo "arm64" )" TARBALL="node-${NODE_VER}-${PLATFORM_NAME}.tar.gz" URL="${NODE_MIRROR}/${NODE_VER}/${TARBALL}" mkdir -p "$NODE_INSTALL_DIR" curl -# -L "$URL" -o "/tmp/$TARBALL" tar -xzf "/tmp/$TARBALL" -C "$NODE_INSTALL_DIR" --strip-components=1 rm -f "/tmp/$TARBALL" chmod +x "$NODE_INSTALL_DIR/bin/node" INSTALL_NODE="$NODE_INSTALL_DIR/bin/node" INSTALL_NPM="$NODE_INSTALL_DIR/bin/npm" echo -e " ${GREEN}Node.js 下载安装完成 ✓${NC}" ;; esac echo "" # ---- Step 4: Copy/Download OpenClaw ---- echo -e " ${BOLD}[4/4] 安装 OpenClaw...${NC}" CORE_INSTALL_DIR="$INSTALL_TARGET/core" case $USE_OPENCLAW in usb) echo -e " ${CYAN}从 U 盘复制 OpenClaw + 插件...${NC}" mkdir -p "$CORE_INSTALL_DIR" cp -R "$APP_DIR/core/"* "$CORE_INSTALL_DIR/" echo -e " ${GREEN}OpenClaw 安装完成 ✓${NC}" ;; download) echo -e " ${CYAN}从国内镜像下载 OpenClaw...${NC}" mkdir -p "$CORE_INSTALL_DIR" cat > "$CORE_INSTALL_DIR/package.json" << 'PKGEOF' { "name": "u-claw-core", "version": "1.0.0", "private": true, "dependencies": { "openclaw": "latest" } } PKGEOF cd "$CORE_INSTALL_DIR" "$INSTALL_NODE" "$INSTALL_NPM" install --registry="$MIRROR" 2>&1 | tail -3 "$INSTALL_NODE" "$INSTALL_NPM" install @sliverp/qqbot@latest --registry="$MIRROR" 2>&1 | tail -2 echo -e " ${GREEN}OpenClaw 下载安装完成 ✓${NC}" ;; esac # ---- Default config ---- CONFIG_PATH="$INSTALL_TARGET/data/.openclaw/openclaw.json" if [ ! -f "$CONFIG_PATH" ]; then cat > "$CONFIG_PATH" << 'CFGEOF' { "gateway": { "mode": "local", "auth": { "token": "uclaw" } } } CFGEOF fi # ---- Copy HTML pages ---- for f in Config.html U-Claw.html; do [ -f "$UCLAW_DIR/$f" ] && cp "$UCLAW_DIR/$f" "$INSTALL_TARGET/" done # ---- Create launch script ---- cat > "$INSTALL_TARGET/start.sh" << 'STARTEOF' #!/bin/bash DIR="$(cd "$(dirname "$0")" && pwd)" ARCH=$(uname -m) NODE_PLATFORM="node-linux-$( [ "$ARCH" = "x86_64" ] && echo "x64" || echo "arm64" )" NODE_BIN="$DIR/runtime/$NODE_PLATFORM/bin/node" [ ! -f "$NODE_BIN" ] && NODE_BIN="$(which node)" CORE_DIR="$DIR/core" OPENCLAW_MJS="$CORE_DIR/node_modules/openclaw/openclaw.mjs" export OPENCLAW_HOME="$DIR/data" export OPENCLAW_STATE_DIR="$DIR/data/.openclaw" export OPENCLAW_CONFIG_PATH="$DIR/data/.openclaw/openclaw.json" PORT=18789 while ss -tlnp 2>/dev/null | grep -q ":$PORT " || netstat -tlnp 2>/dev/null | grep -q ":$PORT "; do PORT=$((PORT + 1)) [ $PORT -gt 18799 ] && echo "No available port" && exit 1 done cd "$CORE_DIR" "$NODE_BIN" "$OPENCLAW_MJS" gateway run --allow-unconfigured --force --port $PORT & PID=$! for i in $(seq 1 30); do sleep 0.5 if curl -s -o /dev/null "http://127.0.0.1:$PORT/" 2>/dev/null; then xdg-open "http://127.0.0.1:$PORT/#token=uclaw" 2>/dev/null || echo "Open: http://127.0.0.1:$PORT/#token=uclaw" break fi done wait $PID STARTEOF chmod +x "$INSTALL_TARGET/start.sh" # ---- Create desktop shortcut ---- DESKTOP_FILE="$HOME/.local/share/applications/u-claw.desktop" mkdir -p "$HOME/.local/share/applications" cat > "$DESKTOP_FILE" << DESKEOF [Desktop Entry] Name=U-Claw Comment=Portable AI Agent Exec=bash $INSTALL_TARGET/start.sh Terminal=true Type=Application Categories=Utility; DESKEOF echo "" # ---- Summary ---- INSTALL_SIZE=$(du -sh "$INSTALL_TARGET" | cut -f1) echo -e " ${GREEN}${BOLD}╔══════════════════════════════════════╗" echo -e " ║ ✅ 安装成功! ║" echo -e " ╚══════════════════════════════════════╝${NC}" echo "" echo -e " ${BOLD}安装位置:${NC} $INSTALL_TARGET" echo -e " ${BOLD}大小:${NC} $INSTALL_SIZE" echo "" echo -e " ${BOLD}启动方式:${NC}" echo -e " 终端运行: ${CYAN}bash ~/.uclaw/start.sh${NC}" echo -e " 或在应用菜单搜索 ${CYAN}U-Claw${NC}" echo "" echo -e " ${BOLD}首次使用:${NC}" echo -e " 启动后浏览器自动打开配置页面" echo -e " 选择 AI 模型 → 填写 API Key → 开始用" echo "" read -p " 按回车关闭..."