10 KiB
部署指南
本文介绍如何从零部署 platform-tools 设备自动化后台。
1. 环境准备
1.1 Python 环境
- Python 3.10+(推荐 3.12)
- 安装后确认
python --version和pip可用
# 验证
python --version # 应输出 3.10+
pip --version
1.2 OpenSTF 服务
本项目依赖 OpenSTF 管理设备池。如已有 STF 服务,跳过本节。
STF 部署参考官方文档:https://github.com/DeviceFarmer/stf
需要获取的信息:
- STF 服务地址(如
http://192.168.20.220:7100) - STF API Token(在 STF 个人设置 → API Keys 里生成)
1.3 adb 工具
项目自带 adb 二进制在 bin/adb/ 目录:
- Windows:
bin/adb/adb.exe+ 依赖 dll(已包含) - Linux:
bin/adb/adb(需chmod +x) - macOS:
bin/adb/adb(需chmod +x)
如需替换为自己的 adb 版本,把对应平台的 adb 放进 bin/adb/ 即可,config.py 会自动识别操作系统。
1.4 设备准备
设备需满足:
- 开启 USB 调试(设置 → 开发者选项)
- 或通过 adb 网络连接(设置 → 开发者选项 → 无线调试,获取 IP:5555)
- 已接入 STF 设备池(STF 显示 present=True, ready=True)
2. 安装部署
2.1 获取代码
# 方式一:直接拷贝项目目录
# 方式二:解压打包文件(python scripts/pack.py 生成的 zip)
2.2 安装依赖
cd platform-tools
pip install -r requirements.txt
依赖清单(requirements.txt):
| 包 | 版本 | 用途 |
|---|---|---|
| Flask | >=2.3,<4.0 | Web 框架 |
| Flask-Login | >=0.6 | 用户认证 |
| Flask-SQLAlchemy | >=3.0,<4.0 | SQLite ORM |
| APScheduler | >=3.10,<4.0 | 定时调度 |
| requests | >=2.28 | HTTP 客户端 |
| uiautomator2 | >=3.0 | Android UI 自动化 |
| uiautodev | >=0.14 | UI 元素抓取 |
| pyaxmlparser | >=0.3.27 | APK 元信息解析 |
uiautomator2 首次连接设备时会自动推送 atx-agent 到设备,无需手动安装。
2.3 修改配置
密钥类配置统一放项目根目录 .env(已被 .gitignore 排除,不会提交到 git;
config.py 不再内置任何密钥):
# .env 示例
STF_TOKEN=你的STF_API_Token
WEB_SECRET_KEY=随机字符串(会话密钥,python -c "import secrets;print(secrets.token_hex(32))" 生成)
TAILSCALE_API_KEY=你的Tailscale_API_key
config.py 只改非密钥项,如 STF_URL:
STF_URL = "http://你的STF地址:端口"
其他配置按需调整:
| 配置项 | 默认值 | 何时修改 |
|---|---|---|
WEB_HOST |
0.0.0.0 |
仅本机访问改为 127.0.0.1 |
WEB_PORT |
18050 |
端口冲突时修改 |
ADB_PATH |
自动识别 | 用自定义 adb 时修改 |
STF_SSH_TARGET |
[email protected] |
维护页"一键重启 STF 容器"的 SSH 目标(需免密登录) |
STF_DOCKER_CONTAINER |
stf |
220 上 STF Docker 容器名(docker ps 查看) |
TAILSCALE_TAILNET |
按邮箱前缀 | tailnet 名称/ID(个人账号一般为登录邮箱前缀) |
未配置
WEB_SECRET_KEY:启动时随机生成(每次重启登录态失效,生产务必配置固定值)。 维护页 Tailscale 前置:.env写入TAILSCALE_API_KEY后重启服务; 未配置时管理分区显示明确提示,不影响其他功能。
维护页 STF 重启前置:本机需能免密 SSH 到部署机(把本机公钥加入目标机
authorized_keys), 且STF_DOCKER_CONTAINER与真实容器名一致;未配置好时按钮会返回明确错误。
2.4 启动服务
方式一:命令行启动
python web_server.py
方式二:Windows 一键启动
双击 start_web.bat:
- 自动提权到管理员
- 添加防火墙规则(支持局域网访问)
- 启动 web_server
2.5 验证部署
- 控制台看到
启动服务: http://localhost:18050/即成功 - 浏览器访问
http://localhost:18050/ - 用
admin/admin123登录 - 监控页应显示 STF 设备池中的设备
3. 生产部署建议
3.1 进程守护
用进程守护工具确保服务自动重启:
Windows(NSSM):
nssm install platform-tools "C:\Python312\python.exe" "D:\platform-tools\web_server.py"
nssm start platform-tools
Linux(systemd):
# /etc/systemd/system/platform-tools.service
[Unit]
Description=Platform Tools Web Server
After=network.target
[Service]
Type=simple
User=www
WorkingDirectory=/opt/platform-tools
ExecStart=/usr/bin/python3 web_server.py
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
通用脚本(Linux/macOS,无需 systemd):
项目自带 scripts/supervise.sh:web_server 崩溃自动重启、带退避和重启上限(防崩溃死循环)。
# 用 venv 的 python 守护
PYTHON=./.venv/bin/python bash scripts/supervise.sh
进程守护只保证服务重启,不恢复已运行的任务(worker 状态在内存)。
悬空设备自愈:崩溃后残留的设备占用(STF 仍显示占用)可配置启动自动清理。单实例部署时在
.env设置AUTO_RELEASE_STALE_OCCUPY=true,web_server 启动会自动释放本账户残留占用;多实例共用 STF 账户时不要开(会误放另一实例的任务)。默认关,仅启动时提示。
Docker(生产 python-app 容器):
docker-compose 已配置 restart: unless-stopped,web_server 进程退出 → 容器退出 → Docker 自动重启。建议再加健康检查,让编排感知服务存活:
# docker-compose.yaml 的 python-app 服务下添加
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:18050/api/health', timeout=3)"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
3.2 反向代理(可选)
如需 HTTPS 或 80 端口,用 Nginx 反向代理:
server {
listen 80;
server_name auto.example.com;
location / {
proxy_pass http://127.0.0.1:18050;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
3.3 安全加固
- 修改默认密码:登录后立即在"用户"Tab 修改 admin 密码
- 最小权限分配:需要多人使用后台时,在"用户"Tab 创建普通用户并只勾选必要权限 (任务管理/设备控制/应用管理/日志查看),不要把 admin 密码共享出去
- 修改 SECRET_KEY:编辑
web_server.py,把app.config["SECRET_KEY"]改成随机字符串 - 限制访问:生产环境把
WEB_HOST改为127.0.0.1,配合反向代理 - 防火墙:只开放必要端口
3.4 日志管理
- 日志自动滚动(10MB 一份,保留 5 份)
- 日志目录
logs/,可在"日志"Tab 在线查看 - 长期运行建议定期清理或配置 logrotate
3.5 数据备份
- 数据库
data/users.db包含用户/分组/任务数据 - APK 文件在
data/apks/ - 建议定期备份
data/目录
4. 网络配置
4.1 端口说明
| 端口 | 服务 | 说明 |
|---|---|---|
| 18050 | Web 后台 | 主服务端口(config.py 可改) |
| 20242 | uiautodev | 元素抓取服务(自动启动,固定端口) |
| 7100 | STF | STF 服务端口(STF 自己的配置) |
| 5555 | adb | 设备 adb 网络端口(设备端) |
4.2 Windows 端口问题
Windows 可能将某些端口范围划为动态排除范围,导致绑定失败(WinError 10013)。
# 查看排除的端口范围
netsh interface ipv4 show excludedportrange protocol=tcp
如果 18050 在排除范围内,修改 config.py 的 WEB_PORT 到一个不在排除范围内的端口。
或运行 scripts/fix_web.bat(关闭系统代理 + 添加防火墙规则 + 刷新 DNS)。
4.3 局域网访问
WEB_HOST = "0.0.0.0"允许局域网访问- 需要添加防火墙入站规则(
start_web.bat会自动处理) - 局域网其他机器访问
http://部署机IP:18050/
5. 更新升级
5.1 代码更新
# 1. 停止服务
# 2. 替换代码文件(或解压新的 zip)
# 3. 重新安装依赖(如有新增)
pip install -r requirements.txt
# 4. 启动服务
python web_server.py
5.2 数据库迁移
- SQLite 表结构变化时,
init_db()会自动db.create_all()创建新表 - 旧
groups.json/jobs.json首次启动自动迁移到 SQLite - 迁移后 JSON 文件归档为
.migrated(保留备份,不再迁移)
5.3 注意事项
- 修改
core/目录下的文件后必须重启 web_server(debug=False不热重载) - 修改
templates/下的 HTML 文件:Flask 模板默认不缓存,但建议重启确保生效 - 修改
tasks/下的文件后必须重启(任务注册在启动时完成)
6. 故障排查
6.1 启动失败
| 现象 | 原因 | 解决 |
|---|---|---|
ModuleNotFoundError: No module named 'flask' |
依赖未安装 | pip install -r requirements.txt |
WinError 10013 |
端口被排除/权限不足 | 改端口或用管理员运行 |
WinError 10048 |
端口被占用 | 改端口或杀占用进程 |
| STF 获取设备列表失败 | STF 地址/token 错误 | 检查 config.py 的 STF_URL 和 STF_TOKEN |
6.2 设备连接失败
| 现象 | 原因 | 解决 |
|---|---|---|
DeviceOfflineError |
设备掉线/STF provider 卡死 | 检查设备网络/STF 状态 |
u2.connect 超时 |
atx-agent 无响应 | 重启设备/重新推送 atx-agent |
adb connect failed |
设备网络不通/端口未开放 | 检查设备 IP 和 5555 端口 |
| STF 设备显示离线 | STF 状态缓存 | 用"扫描前台App"复测 |
6.3 任务不执行
| 现象 | 原因 | 解决 |
|---|---|---|
| 任务列表有任务但不执行 | 任务未启用 / cron 未到点 | 检查 enabled 和 schedule |
| 立即执行无反应 | 无可用设备 | 检查设备池是否有空闲设备 |
| worker 状态 error | 查看日志的 last_error |
查看 logs/core.log 和 logs/task.log |
| 看门狗误杀 | 长操作未心跳 | 在长循环内加 self.heartbeat() |
6.4 日志查看
# 查看核心日志
# 方式一:Web 后台"日志"Tab
# 方式二:直接看文件
# logs/core.log — STF/adb/worker/task_manager
# logs/task.log — 任务执行
# logs/web.log — Web 请求
# logs/action.log — 操作执行