211 lines
6.7 KiB
Bash
Executable File
211 lines
6.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# 宿主机连接守护:ADB + WS Agent 常驻保活(处理长任务时也不断链)
|
||
# 用法:
|
||
# bash sdk/scripts/connection_keeper_daemon.sh # 前台
|
||
# bash sdk/scripts/connection_keeper_daemon.sh --bg # 后台
|
||
# bash sdk/scripts/connection_keeper_daemon.sh --once # 只跑一轮稳定化
|
||
set -euo pipefail
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
SDK_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||
LAN_ENV="${SDK_ROOT}/config/lan.env"
|
||
REQUESTED_ADB_PORT="${ANDROID_ADB_SERVER_PORT:-}"
|
||
[[ -f "${LAN_ENV}" ]] && source "${LAN_ENV}" || true
|
||
[[ -n "${REQUESTED_ADB_PORT}" ]] && export ANDROID_ADB_SERVER_PORT="${REQUESTED_ADB_PORT}"
|
||
SDK_PORT="${WORKPHONE_SDK_PORT:-8899}"
|
||
INTERVAL="${KEEPER_INTERVAL:-15}"
|
||
FAST_INTERVAL="${KEEPER_FAST_INTERVAL:-8}"
|
||
DEVICE_SERIAL="${DEVICE_SERIAL:-}"
|
||
DEVICE_ID="${DEVICE_ID:-xgfe65eimrrofyws}"
|
||
export ANDROID_ADB_SERVER_PORT="${ANDROID_ADB_SERVER_PORT:-5037}"
|
||
ADB=(adb -P "${ANDROID_ADB_SERVER_PORT}")
|
||
LOG="${SDK_ROOT}/logs/connection_keeper.log"
|
||
PID_FILE="${SDK_ROOT}/logs/connection_keeper.pid"
|
||
|
||
mkdir -p "${SDK_ROOT}/logs"
|
||
|
||
log() { echo "[$(date '+%F %T')] $*" | tee -a "$LOG"; }
|
||
|
||
is_phone_serial() {
|
||
local s="$1"
|
||
local brand
|
||
brand=$("${ADB[@]}" -s "$s" shell getprop ro.product.brand 2>/dev/null | tr -d '\r')
|
||
[[ "$brand" != "haier" ]]
|
||
}
|
||
|
||
pick_serial() {
|
||
if [[ -n "$DEVICE_SERIAL" ]]; then
|
||
if "${ADB[@]}" -s "$DEVICE_SERIAL" get-state 2>/dev/null | grep -qx device && is_phone_serial "$DEVICE_SERIAL"; then
|
||
echo "$DEVICE_SERIAL"
|
||
return
|
||
fi
|
||
fi
|
||
local s
|
||
while IFS= read -r s; do
|
||
[[ -z "$s" ]] && continue
|
||
is_phone_serial "$s" || continue
|
||
echo "$s"
|
||
return
|
||
done < <("${ADB[@]}" devices 2>/dev/null | awk '/\tdevice$/{print $1}')
|
||
}
|
||
|
||
usb_xiaomi_present() {
|
||
ioreg -p IOUSB -l 2>/dev/null | grep -q "Xiaomi" 2>/dev/null
|
||
}
|
||
|
||
try_wireless_ports() {
|
||
local host="${1:-192.168.1.12}"
|
||
if usb_xiaomi_present; then
|
||
log "USB Xiaomi detected → skip wireless port scan (优先等 MTP/授权)"
|
||
return 1
|
||
fi
|
||
ping -c 1 -W 2 "$host" >/dev/null 2>&1 || return 1
|
||
"${ADB[@]}" reconnect offline >/dev/null 2>&1 || true
|
||
local p open_port="" hits=0
|
||
for p in 5555 $(seq 37000 37005); do
|
||
if nc -z -G 1 "$host" "$p" 2>/dev/null; then
|
||
hits=$((hits + 1))
|
||
[[ "$hits" -gt 3 ]] && break
|
||
log "wireless port open ${host}:${p} → adb connect"
|
||
( "${ADB[@]}" connect "${host}:${p}" & pid=$!; sleep 3; kill $pid 2>/dev/null; wait $pid 2>/dev/null ) || true
|
||
if "${ADB[@]}" -s "${host}:${p}" get-state 2>/dev/null | grep -qx device; then
|
||
DEVICE_SERIAL="${host}:${p}"
|
||
echo "$DEVICE_SERIAL"
|
||
return 0
|
||
fi
|
||
"${ADB[@]}" disconnect "${host}:${p}" >/dev/null 2>&1 || true
|
||
fi
|
||
done
|
||
return 1
|
||
}
|
||
|
||
ws_online_count() {
|
||
curl -s "http://127.0.0.1:${SDK_PORT}/api/v3/connection/status" 2>/dev/null | \
|
||
python3 -c "import sys,json;d=json.load(sys.stdin).get('data',{});print(d.get('online_ws_count',0))" 2>/dev/null || echo 0
|
||
}
|
||
|
||
u2_online() {
|
||
curl -s "http://127.0.0.1:${SDK_PORT}/api/v3/devices/${DEVICE_ID}" 2>/dev/null | \
|
||
python3 -c "import sys,json;d=json.load(sys.stdin).get('data',{});print('1' if d.get('quick_status',{}).get('u2') else '0')" 2>/dev/null || echo 0
|
||
}
|
||
|
||
ensure_adb_server() {
|
||
if nc -z 127.0.0.1 "${ANDROID_ADB_SERVER_PORT}" 2>/dev/null; then
|
||
return 0
|
||
fi
|
||
"${ADB[@]}" start-server 2>/dev/null || true
|
||
sleep 1
|
||
}
|
||
|
||
adb_devices_safe() {
|
||
( "${ADB[@]}" devices "$@" & pid=$!; sleep 8; kill "$pid" 2>/dev/null; wait "$pid" 2>/dev/null ) 2>/dev/null || true
|
||
}
|
||
|
||
keeper_once() {
|
||
ensure_adb_server
|
||
|
||
ws="$(ws_online_count)"
|
||
u2_ok="$(u2_online)"
|
||
if [[ "$ws" -ge 1 && "$u2_ok" == "1" ]]; then
|
||
log "ok ws_online=${ws} u2=1"
|
||
return 0
|
||
fi
|
||
if [[ "$ws" -ge 1 ]]; then
|
||
log "ws_online=${ws} but u2=${u2_ok} → continue adb/u2 recovery"
|
||
fi
|
||
|
||
serial="$(pick_serial || true)"
|
||
if [[ -z "$serial" ]]; then
|
||
if usb_xiaomi_present; then
|
||
log "USB 已插入但未 adb device → 请在手机选「传输文件」并允许 USB 调试;或开启无线调试"
|
||
# USB 未授权时仍尝试无线 ADB(与 USB 并行)
|
||
for ip in ${WIRELESS_IPS:-192.168.110.80 192.168.3.1}; do
|
||
if serial="$(try_wireless_ports "$ip" || true)" && [[ -n "$serial" ]]; then
|
||
log "wireless adb ok ${serial}"
|
||
break
|
||
fi
|
||
done
|
||
serial="$(pick_serial || true)"
|
||
else
|
||
for ip in ${WIRELESS_IPS:-192.168.110.80 192.168.110.60 192.168.110.197 192.168.3.1 192.168.1.12}; do
|
||
if serial="$(try_wireless_ports "$ip" || true)" && [[ -n "$serial" ]]; then
|
||
break
|
||
fi
|
||
( "${ADB[@]}" connect "${ip}:5555" & pid=$!; sleep 3; kill "$pid" 2>/dev/null; wait "$pid" 2>/dev/null ) || true
|
||
done
|
||
serial="$(pick_serial || true)"
|
||
fi
|
||
fi
|
||
|
||
if [[ -z "$serial" ]]; then
|
||
log "no adb device — 若手机 Termux Agent 已配置 NAS/frp 寻服,可忽略;否则 USB 授权一次做 OTA"
|
||
bash "${SCRIPT_DIR}/sdk_connection_watcher.sh" --once >>"$LOG" 2>&1 || true
|
||
ws="$(ws_online_count)"
|
||
[[ "$ws" -ge 1 ]] && log "sdk_watcher recovered ws=${ws}" && return 0
|
||
return 1
|
||
fi
|
||
|
||
state="$("${ADB[@]}" -s "$serial" get-state 2>/dev/null || echo offline)"
|
||
if [[ "$state" == "unauthorized" ]]; then
|
||
log "adb unauthorized serial=${serial} → 请在手机点「允许 USB 调试」"
|
||
return 1
|
||
fi
|
||
if [[ "$state" != "device" ]]; then
|
||
log "adb not ready serial=${serial} state=${state}"
|
||
return 1
|
||
fi
|
||
|
||
ws="$(ws_online_count)"
|
||
if [[ "$ws" -ge 1 ]]; then
|
||
log "ok serial=${serial} ws_online=${ws}"
|
||
return 0
|
||
fi
|
||
|
||
log "adb ok but ws=0 → termux/on-device agent serial=${serial}"
|
||
DEVICE_SERIAL="$serial" DEVICE_ID="${DEVICE_ID:-xgfe65eimrrofyws}" \
|
||
bash "${SCRIPT_DIR}/termux_push_and_start_agent.sh" >>"$LOG" 2>&1 || true
|
||
ws="$(ws_online_count)"
|
||
if [[ "$ws" -ge 1 ]]; then
|
||
log "termux/oneclick ok ws_online=${ws}"
|
||
return 0
|
||
fi
|
||
log "still ws=0 after termux_push"
|
||
return 1
|
||
}
|
||
|
||
keeper_loop() {
|
||
log "connection_keeper start interval=${INTERVAL}s fast=${FAST_INTERVAL}s port=${SDK_PORT} lan=${WORKPHONE_LAN_IP:-auto}"
|
||
while true; do
|
||
if keeper_once; then
|
||
sleep "$INTERVAL"
|
||
else
|
||
sleep "$FAST_INTERVAL"
|
||
fi
|
||
done
|
||
}
|
||
|
||
case "${1:-}" in
|
||
--once)
|
||
keeper_once
|
||
;;
|
||
--bg)
|
||
if [[ -f "$PID_FILE" ]] && kill -0 "$(cat "$PID_FILE")" 2>/dev/null; then
|
||
echo "已在运行 PID $(cat "$PID_FILE")"
|
||
exit 0
|
||
fi
|
||
nohup bash "$0" >>"$LOG" 2>&1 &
|
||
echo $! >"$PID_FILE"
|
||
echo "connection_keeper 后台 PID $(cat "$PID_FILE") log=$LOG"
|
||
;;
|
||
--stop)
|
||
if [[ -f "$PID_FILE" ]]; then
|
||
kill "$(cat "$PID_FILE")" 2>/dev/null || true
|
||
rm -f "$PID_FILE"
|
||
echo "已停止"
|
||
fi
|
||
;;
|
||
*)
|
||
keeper_loop
|
||
;;
|
||
esac
|