#!/bin/bash # ================================================================ # 一键恢复脚本 — 5种控制模式全部打通 # 用法: bash connect_all.sh # # 执行前提: 设备已完成 USB 调试授权(设备屏幕点击"允许") # ================================================================ set -e SDK_DIR="$(cd "$(dirname "$0")" && pwd)" APP_DIR="$SDK_DIR/app" SERVER_URL="http://127.0.0.1:8899" WS_URL="ws://127.0.0.1:8899/ws/device" AGENT_APK="$SDK_DIR/android-app/app/build/outputs/apk/debug/app-debug.apk" FRIDA_SERVER="/data/local/tmp/frida-server" RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' ok() { echo -e "${GREEN}✅ $1${NC}"; } warn() { echo -e "${YELLOW}⚠️ $1${NC}"; } fail() { echo -e "${RED}❌ $1${NC}"; } info() { echo -e "${BLUE}ℹ️ $1${NC}"; } PASS=0 FAIL=0 WARN=0 # ================================================================ # 0. 前置检查 # ================================================================ echo "" echo "==========================================" echo " 机擎 SDK — 五通道一键恢复" echo "==========================================" echo "" # 检查 ADB if ! command -v adb &>/dev/null; then fail "ADB 未安装" exit 1 fi # 检查设备 DEVICE_STATUS=$(adb devices | grep -v "List" | grep -v "^$" | head -1) if [ -z "$DEVICE_STATUS" ]; then fail "未检测到设备,请连接 USB" exit 1 fi SERIAL=$(echo "$DEVICE_STATUS" | awk '{print $1}') STATUS=$(echo "$DEVICE_STATUS" | awk '{print $2}') if [ "$STATUS" = "unauthorized" ]; then fail "设备 $SERIAL 未授权" echo "" echo " 请在设备屏幕上:" echo " 1. 找到「允许USB调试」对话框" echo " 2. 勾选「始终允许此计算机」" echo " 3. 点击「确定」" echo "" echo " 授权后重新运行此脚本" exit 1 fi if [ "$STATUS" != "device" ]; then fail "设备状态异常: $STATUS" exit 1 fi ok "ADB 已连接: $SERIAL ($STATUS)" PASS=$((PASS+1)) # 获取设备信息 MODEL=$(adb -s "$SERIAL" shell getprop ro.product.model 2>/dev/null | tr -d '\r') ANDROID=$(adb -s "$SERIAL" shell getprop ro.build.version.release 2>/dev/null | tr -d '\r') ANDROID_ID=$(adb -s "$SERIAL" shell settings get secure android_id 2>/dev/null | tr -d '\r') DEVICE_ID=$(echo -n "$ANDROID_ID" | md5 -q 2>/dev/null || echo -n "$ANDROID_ID" | md5sum | awk '{print $1}') echo " 设备: $MODEL | Android $ANDROID" echo " 设备ID: $DEVICE_ID" echo "" # ================================================================ # 1. 检查/启动 SDK 服务器 # ================================================================ info "检查 SDK 服务器..." HEALTH=$(curl -s --connect-timeout 3 "$SERVER_URL/health" 2>/dev/null || echo "") if echo "$HEALTH" | grep -q '"healthy"'; then ok "SDK 服务器运行中" PASS=$((PASS+1)) else warn "SDK 服务器未运行,正在启动..." lsof -ti :8899 2>/dev/null | xargs kill -9 2>/dev/null || true sleep 2 cd "$APP_DIR" nohup python3 -m uvicorn main:app --host 0.0.0.0 --port 8899 --reload > /tmp/sdk_server.log 2>&1 & sleep 5 HEALTH=$(curl -s --connect-timeout 5 "$SERVER_URL/health" 2>/dev/null || echo "") if echo "$HEALTH" | grep -q '"healthy"'; then ok "SDK 服务器已启动" PASS=$((PASS+1)) else fail "SDK 服务器启动失败,查看 /tmp/sdk_server.log" FAIL=$((FAIL+1)) fi fi echo "" # ================================================================ # 2. ADB 反向代理(让设备 127.0.0.1:8899 指向 Mac) # ================================================================ info "设置 ADB 反向代理..." adb -s "$SERIAL" reverse tcp:8899 tcp:8899 2>/dev/null if [ $? -eq 0 ]; then ok "ADB reverse 已设置 (设备 127.0.0.1:8899 → Mac)" PASS=$((PASS+1)) else fail "ADB reverse 设置失败" FAIL=$((FAIL+1)) fi echo "" # ================================================================ # 3. 通道一:ADB 静默控制验证 # ================================================================ info "验证 ADB 静默控制..." ADB_SCREENSHOT=$(adb -s "$SERIAL" shell screencap -p /sdcard/test_connect.png 2>&1) if [ $? -eq 0 ]; then ok "ADB 控制可用 (截图成功)" adb -s "$SERIAL" shell rm -f /sdcard/test_connect.png 2>/dev/null PASS=$((PASS+1)) else fail "ADB 控制失败: $ADB_SCREENSHOT" FAIL=$((FAIL+1)) fi echo "" # ================================================================ # 4. 通道二:Agent WebSocket 验证 # ================================================================ info "验证 Agent WebSocket..." AGENT_INSTALLED=$(adb -s "$SERIAL" shell pm list packages 2>/dev/null | grep "com.workphone.agent" || echo "") if [ -z "$AGENT_INSTALLED" ]; then warn "Agent App 未安装" if [ -f "$AGENT_APK" ]; then info "正在安装 Agent App..." adb -s "$SERIAL" install -r -g "$AGENT_APK" 2>/dev/null if [ $? -eq 0 ]; then ok "Agent App 安装成功" else fail "Agent App 安装失败" FAIL=$((FAIL+1)) fi else warn "APK 不存在: $AGENT_APK,跳过安装" WARN=$((WARN+1)) fi else ok "Agent App 已安装" fi # 启动 Agent App adb -s "$SERIAL" shell am start -n com.workphone.agent/.MainActivity 2>/dev/null sleep 3 # 检查 WebSocket 连接 HEALTH2=$(curl -s --connect-timeout 3 "$SERVER_URL/health" 2>/dev/null || echo "") WS_ONLINE=$(echo "$HEALTH2" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('devices_online',0))" 2>/dev/null || echo "0") if [ "$WS_ONLINE" -gt 0 ] 2>/dev/null; then ok "Agent WebSocket 在线 (设备数: $WS_ONLINE)" PASS=$((PASS+1)) else warn "Agent WebSocket 未连接 (可能需要在App中手动连接)" WARN=$((WARN+1)) fi echo "" # ================================================================ # 5. 通道三:Hook / Frida 验证 # ================================================================ info "验证 Hook / Frida..." IS_ROOTED=$(adb -s "$SERIAL" shell "su -c 'id' 2>/dev/null" | tr -d '\r') if echo "$IS_ROOTED" | grep -q "uid=0"; then ok "Root 权限可用" FRIDA_RUNNING=$(adb -s "$SERIAL" shell "su -c 'ps -ef | grep frida-server | grep -v grep'" 2>/dev/null | tr -d '\r') if [ -n "$FRIDA_RUNNING" ]; then ok "Frida Server 运行中" PASS=$((PASS+1)) else FRIDA_EXISTS=$(adb -s "$SERIAL" shell "su -c 'ls $FRIDA_SERVER'" 2>/dev/null | tr -d '\r') if echo "$FRIDA_EXISTS" | grep -q "frida-server"; then info "启动 Frida Server..." adb -s "$SERIAL" shell "su -c 'chmod 755 $FRIDA_SERVER && $FRIDA_SERVER -D &'" 2>/dev/null & sleep 3 FRIDA_CHECK=$(adb -s "$SERIAL" shell "su -c 'ps -ef | grep frida-server | grep -v grep'" 2>/dev/null) if [ -n "$FRIDA_CHECK" ]; then ok "Frida Server 已启动" PASS=$((PASS+1)) else warn "Frida Server 启动失败(可能需要 Magisk 授权)" WARN=$((WARN+1)) fi else warn "Frida Server 未部署到设备" WARN=$((WARN+1)) fi fi else warn "Root 权限不可用(需要 Magisk 授权 Shell)" WARN=$((WARN+1)) fi echo "" # ================================================================ # 6. 通道四:AI Agent 验证 # ================================================================ info "验证 AI Agent..." AI_STATUS=$(curl -s --connect-timeout 3 "$SERVER_URL/api/v3/ai/status" 2>/dev/null || echo "") if echo "$AI_STATUS" | grep -q '"available"'; then ok "AI 引擎可用" PASS=$((PASS+1)) else AI_AVAIL=$(echo "$AI_STATUS" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('data',{}).get('available',''))" 2>/dev/null || echo "") if [ "$AI_AVAIL" = "True" ] || [ "$AI_AVAIL" = "true" ]; then ok "AI 引擎可用" PASS=$((PASS+1)) else warn "AI 引擎不可用(需配置 DEEPSEEK_API_KEY 或 Ollama)" WARN=$((WARN+1)) fi fi echo "" # ================================================================ # 7. 通道五:scrcpy 验证 # ================================================================ info "验证 scrcpy..." if command -v scrcpy &>/dev/null; then ok "scrcpy 已安装" PASS=$((PASS+1)) info "可运行: scrcpy -s $SERIAL --max-size 1024" else warn "scrcpy 未安装 (brew install scrcpy)" WARN=$((WARN+1)) fi echo "" # ================================================================ # 8. 心跳监控验证 # ================================================================ info "验证 AI 心跳监控..." HB_DASH=$(curl -s --connect-timeout 3 "$SERVER_URL/api/v3/heartbeat/dashboard" 2>/dev/null || echo "") if echo "$HB_DASH" | grep -q '"total_devices"'; then TOTAL=$(echo "$HB_DASH" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('data',{}).get('total_devices',0))" 2>/dev/null || echo "0") AVG=$(echo "$HB_DASH" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('data',{}).get('avg_score',0))" 2>/dev/null || echo "0") ok "心跳监控在线 (设备: $TOTAL, 平均健康分: $AVG)" PASS=$((PASS+1)) else warn "心跳监控数据暂无(等待首次心跳)" WARN=$((WARN+1)) fi echo "" # ================================================================ # 9. 注册设备映射 # ================================================================ info "注册设备映射..." REGISTER_RESULT=$(curl -s -X POST --connect-timeout 3 "$SERVER_URL/api/v3/devices/$DEVICE_ID/connection-modes" 2>/dev/null || echo "") if [ -n "$REGISTER_RESULT" ]; then ok "连接模式已评估" PASS=$((PASS+1)) fi echo "" # ================================================================ # 总结 # ================================================================ echo "==========================================" echo " 恢复结果" echo "==========================================" echo "" echo -e " ${GREEN}通过: $PASS${NC}" echo -e " ${YELLOW}警告: $WARN${NC}" echo -e " ${RED}失败: $FAIL${NC}" echo "" if [ $FAIL -eq 0 ]; then echo -e "${GREEN}所有关键通道已就绪!${NC}" else echo -e "${RED}有 $FAIL 个通道需要修复${NC}" fi echo "" echo " 控制台: $SERVER_URL" echo " API文档: $SERVER_URL/docs" echo " 设备ID: $DEVICE_ID" echo " ADB序列号: $SERIAL" echo ""