feat: publish workphone SDK deployment and API docs
This commit is contained in:
392
sdk/agent/install.sh
Normal file
392
sdk/agent/install.sh
Normal file
@@ -0,0 +1,392 @@
|
||||
#!/data/data/com.termux/files/usr/bin/bash
|
||||
#
|
||||
# ================================================================
|
||||
# 云同步服务 v3.1 - Termux 一键安装脚本
|
||||
# ================================================================
|
||||
#
|
||||
# 使用方法(在 Termux 中执行):
|
||||
#
|
||||
# 方式1 - 从服务器远程安装:
|
||||
# curl -sL http://服务器IP:8899/install.sh | bash -s -- --server ws://服务器IP:8899/ws/device
|
||||
#
|
||||
# 方式2 - 本地安装:
|
||||
# bash install.sh --server ws://192.168.1.100:8899/ws/device
|
||||
#
|
||||
# 方式3 - 全自动安装(批量部署用):
|
||||
# bash install.sh --server ws://IP:8899/ws/device --auto --disguise
|
||||
#
|
||||
# 方式4 - 带参数:
|
||||
# bash install.sh \
|
||||
# --server ws://192.168.1.100:8899/ws/device \
|
||||
# --project cunkebao \
|
||||
# --ai-url http://服务器IP:3102 \
|
||||
# --ai-key YOUR_KEY
|
||||
#
|
||||
# ================================================================
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
# ---------- 颜色 ----------
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[0;33m'
|
||||
CYAN='\033[0;36m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
info() { echo -e "${GREEN}[INFO]${NC} $*"; }
|
||||
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||||
error() { echo -e "${RED}[ERROR]${NC} $*"; }
|
||||
|
||||
# ---------- 默认值 ----------
|
||||
SERVER_URL=""
|
||||
HEARTBEAT=10
|
||||
PROJECT_ID="cunkebao"
|
||||
AGENT_DIR="$HOME/cloud-sync"
|
||||
AI_ENABLED="true"
|
||||
AI_URL=""
|
||||
AI_KEY=""
|
||||
AI_MODEL="auto"
|
||||
AI_INTERVAL=60
|
||||
INSTALL_FRIDA="false"
|
||||
AUTO_MODE="false"
|
||||
DISGUISE_MODE="false"
|
||||
|
||||
# ---------- 参数解析 ----------
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--server|-s) SERVER_URL="$2"; shift 2 ;;
|
||||
--heartbeat) HEARTBEAT="$2"; shift 2 ;;
|
||||
--project|-p) PROJECT_ID="$2"; shift 2 ;;
|
||||
--dir) AGENT_DIR="$2"; shift 2 ;;
|
||||
--ai-url) AI_URL="$2"; shift 2 ;;
|
||||
--ai-key) AI_KEY="$2"; shift 2 ;;
|
||||
--ai-model) AI_MODEL="$2"; shift 2 ;;
|
||||
--ai-interval) AI_INTERVAL="$2"; shift 2 ;;
|
||||
--no-ai) AI_ENABLED="false"; shift ;;
|
||||
--frida) INSTALL_FRIDA="true"; shift ;;
|
||||
--auto) AUTO_MODE="true"; shift ;;
|
||||
--disguise) DISGUISE_MODE="true"; shift ;;
|
||||
--help|-h)
|
||||
echo "用法: bash install.sh --server ws://IP:8899/ws/device [选项]"
|
||||
echo ""
|
||||
echo "选项:"
|
||||
echo " --server, -s 服务器WebSocket地址(必填)"
|
||||
echo " --heartbeat 心跳间隔(秒),默认10"
|
||||
echo " --project, -p 项目ID,默认cunkebao"
|
||||
echo " --dir 安装目录,默认 ~/cloud-sync"
|
||||
echo " --ai-url AI API 地址"
|
||||
echo " --ai-key AI API Key"
|
||||
echo " --ai-model AI 模型,默认auto"
|
||||
echo " --ai-interval AI 周期(秒),默认60"
|
||||
echo " --no-ai 禁用 AI"
|
||||
echo " --frida 同时安装 Frida Server(需Root)"
|
||||
echo " --auto 全自动模式(跳过确认)"
|
||||
echo " --disguise 安装完成后清理痕迹"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
if [[ -z "$SERVER_URL" ]]; then
|
||||
SERVER_URL="$1"
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# ---------- 自动检测设备ID ----------
|
||||
DEVICE_ID=$(getprop ro.serialno 2>/dev/null || echo "")
|
||||
if [[ -z "$DEVICE_ID" ]]; then
|
||||
DEVICE_ID="dev-$(date +%s)"
|
||||
fi
|
||||
|
||||
# ---------- 服务器地址检查 ----------
|
||||
if [[ -z "$SERVER_URL" ]]; then
|
||||
echo ""
|
||||
error "未指定服务器地址!"
|
||||
echo ""
|
||||
echo -e " ${BOLD}用法:${NC} bash install.sh --server ws://服务器IP:8899/ws/device"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ---------- 提取 HTTP 地址(用于下载) ----------
|
||||
HTTP_BASE=$(echo "$SERVER_URL" | sed -E 's|^ws(s?)://|http\1://|' | sed -E 's|/ws/device.*||')
|
||||
|
||||
echo ""
|
||||
echo -e "${BOLD}${CYAN}============================================${NC}"
|
||||
echo -e "${BOLD}${CYAN} 云同步服务 v3.1 安装程序${NC}"
|
||||
echo -e "${BOLD}${CYAN}============================================${NC}"
|
||||
echo ""
|
||||
echo -e " 设备ID: ${BOLD}$DEVICE_ID${NC}"
|
||||
echo -e " 服务器: ${BOLD}$SERVER_URL${NC}"
|
||||
echo -e " 安装目录: ${BOLD}$AGENT_DIR${NC}"
|
||||
echo -e " 自动模式: ${BOLD}${AUTO_MODE}${NC}"
|
||||
echo ""
|
||||
|
||||
# ========== Step 1: 更新 Termux ==========
|
||||
info "[1/7] 更新包管理器..."
|
||||
if [ "$AUTO_MODE" = "true" ]; then
|
||||
yes | pkg update 2>/dev/null || true
|
||||
yes | pkg upgrade 2>/dev/null || true
|
||||
else
|
||||
pkg update -y 2>/dev/null || true
|
||||
pkg upgrade -y 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# ========== Step 2: 安装系统依赖 ==========
|
||||
info "[2/7] 安装系统依赖..."
|
||||
pkg install -y python git 2>/dev/null || true
|
||||
|
||||
if ! command -v pip &>/dev/null; then
|
||||
pkg install -y python-pip 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# ========== Step 3: 安装 Python 依赖 ==========
|
||||
info "[3/7] 安装 Python 依赖..."
|
||||
pip install --upgrade pip 2>/dev/null || true
|
||||
pip install websockets>=12.0 uiautomator2>=3.0.0 adbutils>=2.0.0 httpx>=0.25.0 2>/dev/null || {
|
||||
warn "部分依赖安装失败,尝试逐个安装..."
|
||||
pip install websockets 2>/dev/null || true
|
||||
pip install uiautomator2 2>/dev/null || true
|
||||
pip install adbutils 2>/dev/null || true
|
||||
pip install httpx 2>/dev/null || true
|
||||
}
|
||||
|
||||
# ========== Step 4: 下载代码 ==========
|
||||
info "[4/7] 下载代码..."
|
||||
mkdir -p "$AGENT_DIR"
|
||||
|
||||
DOWNLOAD_OK=false
|
||||
if curl -sf "${HTTP_BASE}/api/v3/agent/download" -o "$AGENT_DIR/archive.tar.gz" 2>/dev/null; then
|
||||
cd "$AGENT_DIR"
|
||||
if tar xzf archive.tar.gz 2>/dev/null; then
|
||||
rm -f archive.tar.gz
|
||||
DOWNLOAD_OK=true
|
||||
info "代码下载成功"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$DOWNLOAD_OK" = false ]; then
|
||||
warn "无法从服务器下载,请手动复制代码到 $AGENT_DIR"
|
||||
fi
|
||||
|
||||
# ========== Step 5: 生成配置文件 ==========
|
||||
info "[5/7] 生成配置文件..."
|
||||
|
||||
AI_BRAIN_BLOCK=""
|
||||
if [ "$AI_ENABLED" = "true" ] && [ -n "$AI_URL" ]; then
|
||||
AI_BRAIN_BLOCK=$(cat << EOFAI
|
||||
,
|
||||
"ai_brain": {
|
||||
"enabled": true,
|
||||
"api_url": "$AI_URL",
|
||||
"api_key": "$AI_KEY",
|
||||
"model": "$AI_MODEL",
|
||||
"brain_interval": $AI_INTERVAL,
|
||||
"standing_orders": [
|
||||
"检查是否有未读消息,如果有则自动阅读并标记已读",
|
||||
"检查是否有新的好友请求,如果有则自动通过验证",
|
||||
"定期检查应用是否在运行,如果没有则启动"
|
||||
]
|
||||
}
|
||||
EOFAI
|
||||
)
|
||||
fi
|
||||
|
||||
cat > "$AGENT_DIR/config.json" << EOFCONFIG
|
||||
{
|
||||
"device_id": "$DEVICE_ID",
|
||||
"server_url": "$SERVER_URL",
|
||||
"heartbeat_interval": $HEARTBEAT,
|
||||
"project_id": "$PROJECT_ID"$AI_BRAIN_BLOCK
|
||||
}
|
||||
EOFCONFIG
|
||||
|
||||
info "配置已写入: $AGENT_DIR/config.json"
|
||||
|
||||
# ========== Step 6: 安装 Frida(可选,需Root) ==========
|
||||
if [ "$INSTALL_FRIDA" = "true" ]; then
|
||||
info "[6/7] 安装 Frida Server..."
|
||||
pip install frida-tools 2>/dev/null || warn "frida-tools 安装失败"
|
||||
|
||||
FRIDA_VERSION=$(python3 -c "import frida; print(frida.__version__)" 2>/dev/null || echo "")
|
||||
if [ -n "$FRIDA_VERSION" ]; then
|
||||
ARCH=$(getprop ro.product.cpu.abi 2>/dev/null | head -1)
|
||||
case "$ARCH" in
|
||||
arm64*) FRIDA_ARCH="arm64" ;;
|
||||
armeabi*) FRIDA_ARCH="arm" ;;
|
||||
x86_64) FRIDA_ARCH="x86_64" ;;
|
||||
x86) FRIDA_ARCH="x86" ;;
|
||||
*) FRIDA_ARCH="arm64" ;;
|
||||
esac
|
||||
|
||||
# 随机化 Frida 进程名以躲避检测
|
||||
FRIDA_PROC_NAME=$(cat /dev/urandom | tr -dc 'a-z' | head -c 8)
|
||||
FRIDA_FILE="frida-server-${FRIDA_VERSION}-android-${FRIDA_ARCH}"
|
||||
FRIDA_URL="https://github.com/frida/frida/releases/download/${FRIDA_VERSION}/${FRIDA_FILE}.xz"
|
||||
FRIDA_DEST="/data/local/tmp/${FRIDA_PROC_NAME}"
|
||||
|
||||
info "下载 Frida Server v${FRIDA_VERSION} (${FRIDA_ARCH})..."
|
||||
info "Frida 进程名: ${FRIDA_PROC_NAME}"
|
||||
if curl -sL "$FRIDA_URL" -o "/tmp/${FRIDA_FILE}.xz" 2>/dev/null; then
|
||||
xz -d "/tmp/${FRIDA_FILE}.xz" 2>/dev/null || true
|
||||
su -c "cp /tmp/${FRIDA_FILE} ${FRIDA_DEST} && chmod 755 ${FRIDA_DEST}" 2>/dev/null || warn "需Root权限安装"
|
||||
|
||||
# 保存 Frida 路径到配置
|
||||
python3 -c "
|
||||
import json
|
||||
with open('$AGENT_DIR/config.json') as f: cfg = json.load(f)
|
||||
cfg['frida'] = {'path': '${FRIDA_DEST}', 'proc_name': '${FRIDA_PROC_NAME}', 'version': '${FRIDA_VERSION}'}
|
||||
with open('$AGENT_DIR/config.json', 'w') as f: json.dump(cfg, f, indent=2, ensure_ascii=False)
|
||||
" 2>/dev/null || true
|
||||
|
||||
info "Frida Server 已安装: ${FRIDA_DEST}"
|
||||
else
|
||||
warn "Frida 下载失败,请手动安装"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
info "[6/7] 跳过 Frida(未指定 --frida)"
|
||||
fi
|
||||
|
||||
# ========== Step 7: 创建启动脚本 ==========
|
||||
info "[7/7] 创建启动脚本..."
|
||||
|
||||
# --- 前台启动 ---
|
||||
cat > "$AGENT_DIR/start.sh" << 'EOFSTART'
|
||||
#!/data/data/com.termux/files/usr/bin/bash
|
||||
cd "$(dirname "$0")"
|
||||
exec python3 agent.py "$@"
|
||||
EOFSTART
|
||||
chmod +x "$AGENT_DIR/start.sh"
|
||||
|
||||
# 兼容性符号链接
|
||||
ln -sf "$AGENT_DIR/agent.py" "$AGENT_DIR/sync_worker.py" 2>/dev/null || true
|
||||
|
||||
# --- 后台启动 ---
|
||||
cat > "$AGENT_DIR/start_bg.sh" << 'EOFBG'
|
||||
#!/data/data/com.termux/files/usr/bin/bash
|
||||
cd "$(dirname "$0")"
|
||||
if [ -f service.pid ]; then
|
||||
OLD_PID=$(cat service.pid)
|
||||
if kill -0 "$OLD_PID" 2>/dev/null; then
|
||||
echo "停止旧进程 PID=$OLD_PID ..."
|
||||
kill "$OLD_PID" 2>/dev/null
|
||||
sleep 1
|
||||
fi
|
||||
rm -f service.pid
|
||||
fi
|
||||
nohup python3 agent.py "$@" > service.log 2>&1 &
|
||||
NEW_PID=$!
|
||||
echo "$NEW_PID" > service.pid
|
||||
echo "已后台启动 PID=$NEW_PID"
|
||||
echo " 日志: tail -f $(pwd)/service.log"
|
||||
echo " 停止: bash $(pwd)/stop.sh"
|
||||
EOFBG
|
||||
chmod +x "$AGENT_DIR/start_bg.sh"
|
||||
|
||||
# --- 停止脚本 ---
|
||||
cat > "$AGENT_DIR/stop.sh" << 'EOFSTOP'
|
||||
#!/data/data/com.termux/files/usr/bin/bash
|
||||
cd "$(dirname "$0")"
|
||||
if [ -f service.pid ]; then
|
||||
PID=$(cat service.pid)
|
||||
if kill -0 "$PID" 2>/dev/null; then
|
||||
kill "$PID"
|
||||
echo "已停止 PID=$PID"
|
||||
else
|
||||
echo "进程 $PID 不存在"
|
||||
fi
|
||||
rm -f service.pid
|
||||
else
|
||||
PIDS=$(pgrep -f "python3.*agent.py" 2>/dev/null || true)
|
||||
if [ -n "$PIDS" ]; then
|
||||
kill $PIDS 2>/dev/null
|
||||
echo "已停止: $PIDS"
|
||||
else
|
||||
echo "没有运行中的服务进程"
|
||||
fi
|
||||
fi
|
||||
EOFSTOP
|
||||
chmod +x "$AGENT_DIR/stop.sh"
|
||||
|
||||
# --- 状态查看 ---
|
||||
cat > "$AGENT_DIR/status.sh" << 'EOFSTATUS'
|
||||
#!/data/data/com.termux/files/usr/bin/bash
|
||||
cd "$(dirname "$0")"
|
||||
echo "========== 服务状态 =========="
|
||||
if [ -f service.pid ]; then
|
||||
PID=$(cat service.pid)
|
||||
if kill -0 "$PID" 2>/dev/null; then
|
||||
echo "运行中 PID=$PID"
|
||||
else
|
||||
echo "已退出 (PID=$PID)"
|
||||
fi
|
||||
else
|
||||
PIDS=$(pgrep -f "python3.*agent.py" 2>/dev/null || true)
|
||||
if [ -n "$PIDS" ]; then
|
||||
echo "运行中 PID=$PIDS"
|
||||
else
|
||||
echo "未运行"
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
echo "配置:"
|
||||
[ -f config.json ] && cat config.json
|
||||
echo ""
|
||||
echo "最近日志:"
|
||||
[ -f service.log ] && tail -5 service.log || echo "(无日志)"
|
||||
echo "================================"
|
||||
EOFSTATUS
|
||||
chmod +x "$AGENT_DIR/status.sh"
|
||||
|
||||
# --- Termux:Boot 开机自启 ---
|
||||
mkdir -p "$HOME/.termux/boot"
|
||||
cat > "$HOME/.termux/boot/cloud-sync.sh" << EOFBOOT
|
||||
#!/data/data/com.termux/files/usr/bin/bash
|
||||
sleep 15
|
||||
cd "$AGENT_DIR"
|
||||
bash start_bg.sh
|
||||
EOFBOOT
|
||||
chmod +x "$HOME/.termux/boot/cloud-sync.sh"
|
||||
|
||||
# ========== 伪装清理 ==========
|
||||
if [ "$DISGUISE_MODE" = "true" ]; then
|
||||
info "清理安装痕迹..."
|
||||
rm -f "$AGENT_DIR/archive.tar.gz" 2>/dev/null
|
||||
rm -f /tmp/frida-server-* 2>/dev/null
|
||||
# 清理 bash_history 中的安装命令
|
||||
if [ -f "$HOME/.bash_history" ]; then
|
||||
sed -i '/install\.sh/d; /workphone/d; /frida/d; /agent/d' "$HOME/.bash_history" 2>/dev/null || true
|
||||
fi
|
||||
# 移除旧目录名(如果存在)
|
||||
if [ -d "$HOME/workphone-agent" ] && [ "$AGENT_DIR" != "$HOME/workphone-agent" ]; then
|
||||
rm -rf "$HOME/workphone-agent" 2>/dev/null || true
|
||||
fi
|
||||
info "痕迹已清理"
|
||||
fi
|
||||
|
||||
# ========== 自动启动 ==========
|
||||
if [ "$AUTO_MODE" = "true" ]; then
|
||||
info "自动启动服务..."
|
||||
cd "$AGENT_DIR"
|
||||
bash start_bg.sh
|
||||
fi
|
||||
|
||||
# ========== 完成 ==========
|
||||
echo ""
|
||||
echo -e "${BOLD}${GREEN}============================================${NC}"
|
||||
echo -e "${BOLD}${GREEN} 安装完成!${NC}"
|
||||
echo -e "${BOLD}${GREEN}============================================${NC}"
|
||||
echo ""
|
||||
echo -e " ${BOLD}启动:${NC} bash $AGENT_DIR/start.sh"
|
||||
echo -e " ${BOLD}后台运行:${NC} bash $AGENT_DIR/start_bg.sh"
|
||||
echo -e " ${BOLD}查看状态:${NC} bash $AGENT_DIR/status.sh"
|
||||
echo -e " ${BOLD}停止:${NC} bash $AGENT_DIR/stop.sh"
|
||||
echo -e " ${BOLD}查看日志:${NC} tail -f $AGENT_DIR/service.log"
|
||||
echo ""
|
||||
echo -e " 服务会自动连接并保持心跳。"
|
||||
echo -e " 开机自启需要安装 ${BOLD}Termux:Boot${NC} 插件。"
|
||||
echo ""
|
||||
echo -e "${BOLD}${CYAN}============================================${NC}"
|
||||
Reference in New Issue
Block a user