# 多账户交易中控 — 部署文档(含 PM2) 本文档说明在 **Ubuntu / Linux** 上部署 **manual_trading_hub**(复盘系统中控:监控区、系统设置、登录保护)的推荐步骤。 - 功能与界面:[使用说明.md](./使用说明.md) - 故障实录:[常见问题.md](./常见问题.md) - 环境变量模板:[.env.example](./.env.example) --- ## 一、部署目标 | 组件 | 作用 | 默认监听 | |------|------|----------| | **hub.py** | 中控 Web + API | `0.0.0.0:5100` | | **agent.py × N** | 各账户持仓 / 紧急全平 | `127.0.0.1:15200`~`15203` | | **crypto_monitor_*.app** | 策略、关键位、下单逻辑 | 各目录 `.env` 的 `APP_PORT` | - 账户列表与 URL 由 **`hub_settings.json`**(网页「系统设置」保存)或内置默认维护;**不再使用** `HUB_AGENTS`。 - 四实例 Flask **无需为中控改业务代码**(已注册 `hub_bridge`);与中控并行运行。 --- ## 二、前置条件 1. **Python 3.10+**、`python3-venv`、`pip`。 2. **Node.js + npm**(用于安装 PM2):`sudo npm i -g pm2`。 3. 各 `crypto_monitor_*` 目录已 **`cp .env.example .env`** 并填好 API 密钥。 4. 端口无冲突:`5100`、`15200`~`15203`、各实例 `APP_PORT`(5000/5001/5002/5004)。 5. 建议代码路径:`/opt/crypto_monitor/`(下文用此示例,请按实际路径替换)。 --- ## 三、安装中控依赖 ```bash cd /opt/crypto_monitor/manual_trading_hub python3 -m venv .venv source .venv/bin/activate # 激活 venv(当前终端后续 pip/python 走虚拟环境) pip install -r requirements.txt cp .env.example .env # 编辑 .env:HUB_PORT、HUB_DISABLED_IDS、公网时 HUB_BRIDGE_TOKEN 等 chmod +x scripts/run_hub.sh scripts/run_agent.sh scripts/pm2_hub.sh scripts/pm2_agents.sh chmod +x scripts/fix_hub_deps.sh scripts/verify_hub_deploy.sh scripts/fix_env_crlf.sh deactivate # 可选;交给 PM2 时不必保持激活 ``` **依赖说明**:`requirements.txt` 含 **`python-multipart`**(FastAPI 表单解析;旧版若保留下单接口时需要)。当前中控**已移除下单区**,但仍建议安装完整依赖。 说明: - **安装依赖**:`source .venv/bin/activate` 后用 `pip install` 即可;不写 `activate` 时也可用 **`.venv/bin/pip install -r requirements.txt`**(效果相同)。 - **PM2 启动**:由 `scripts/run_hub.sh` 固定调用 **`.venv/bin/python`**,**不依赖**你是否在 shell 里激活过 venv。 子代理也使用 **本目录 `.venv`** 里的 Python(与各策略 Flask 的 venv 可分开)。 --- ## 四、推荐启动顺序 ``` 1. 各实例 Flask(APP_PORT) ← 各 crypto_monitor_* 目录 ecosystem.config.cjs 2. 中控 + 子代理(5100 + 15200~15203) ← 本目录一条 PM2 命令同时启动 ``` **`ecosystem.config.cjs` 会一次拉起 4 个 agent + 1 个 hub**,无需再单独 `pm2 start` 子代理。 仅反代中控到公网时:Flask / agent 仍只监听 **127.0.0.1**;系统设置里 URL 填 `http://127.0.0.1:端口`。 --- ## 五、PM2 托管(hub + agent 一起启动,推荐) ### 5.1 一条命令启动全部 | 文件 | 包含进程 | |------|----------| | `ecosystem.config.cjs` | `manual-agent-binance` / `okx` / `gate` / `gate-bot` + **`manual-trading-hub`** | `run_hub.sh` 加载 **`manual_trading_hub/.env`** 后执行 `hub.py`;各 agent 经 **`run_agent.sh`** 在对应策略目录加载 **`.env`**(含 API 密钥),再执行 `agent.py`。 ```bash cd /opt/crypto_monitor/manual_trading_hub source .venv/bin/activate pip install -r requirements.txt cp .env.example .env pm2 start ecosystem.config.cjs # 5 个进程一起起 pm2 save # 或 bash scripts/pm2_hub.sh start ``` ### 5.2 PM2 进程一览 | 进程名 | 工作目录 | 端口/说明 | |--------|----------|-----------| | manual-agent-binance | crypto_monitor_binance | agent `15200` | | manual-agent-okx | crypto_monitor_okx | agent `15201` | | manual-agent-gate | crypto_monitor_gate | agent `15202` | | manual-agent-gate-bot | crypto_monitor_gate_bot | agent `15203` | | manual-trading-hub | manual_trading_hub | hub `5100` | OKX 子代理会启动,但中控默认 `HUB_DISABLED_IDS=1` 不参与监控;不用 OKX 可 `pm2 stop manual-agent-okx`。 ### 5.3 常用运维命令 ```bash pm2 status pm2 logs manual-trading-hub --lines 200 pm2 restart ecosystem.config.cjs # 重启 hub + 全部 agent bash scripts/pm2_hub.sh restart # 同上 bash scripts/pm2_hub.sh stop bash scripts/pm2_hub.sh logs ``` 仅重启中控、不动 agent: ```bash pm2 restart manual-trading-hub ``` 仅重启子代理: ```bash pm2 restart manual-agent-binance manual-agent-gate manual-agent-gate-bot # 或 bash scripts/pm2_agents.sh restart ``` ### 5.4 开机自启 ```bash pm2 save pm2 startup # 按终端提示执行一行 sudo 命令后,再 pm2 save ``` ### 5.5 与各实例 Flask 一起查看 ```bash pm2 status # 示例同时存在: # manual-trading-hub、manual-agent-* # crypto_binance / crypto_gate …(各策略目录自有 ecosystem.config.cjs) ``` --- ## 六、手动启动(不用 PM2 时) 需**分别**起 agent 与 hub(与 PM2 合并启动不同): ```bash # 子代理:scripts/start_agents_3screen.sh 或每目录手动 agent.py # 中控: cd /opt/crypto_monitor/manual_trading_hub bash scripts/run_hub.sh ``` --- ## 七、浏览器验收 1. **http://127.0.0.1:5100/login** — 若 `.env` 已设 `HUB_PASSWORD`,用 `HUB_USERNAME` / `HUB_PASSWORD` 登录。 2. **http://127.0.0.1:5100/monitor** — 已启用账户显示持仓;Flask 已起时有关键位/趋势信息。 3. **http://127.0.0.1:5100/settings** — 保存后生成 `hub_settings.json`。 4. 监控卡片 **「实例」** — 在各 `crypto_monitor_*` 网页做下单、关键位、趋势;中控**不提供**下单表单。 **命令行验收**(推荐): ```bash cd /opt/crypto_monitor/manual_trading_hub bash scripts/verify_hub_deploy.sh ``` 应看到:`OK: 无 api_trade_key`,`HTTP 200`,JSON 含 `"build":"20260521-no-trade-ui"`。 ```bash curl -s http://127.0.0.1:5100/api/ping curl -s http://127.0.0.1:15200/status | head -c 200 ``` --- ## 八、仅反代中控到公网(实例不反代) 1. Nginx/Caddy 反代到 **`127.0.0.1:5100`**,配置 **HTTPS**。 2. 反代需传递(登录 Cookie 正确识别 HTTPS): ```nginx proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; ``` 3. `manual_trading_hub/.env` **务必设置**: ```env HUB_USERNAME=你的用户名 HUB_PASSWORD=你的强密码 HUB_SESSION_SECRET=随机长串 HUB_COOKIE_SECURE=true ``` 4. `hub_settings.json` 中 Flask/Agent 保持 **`http://127.0.0.1:...`**(中控本机调 API)。 5. 四实例 **`APP_AUTH_DISABLED=false`** + 与中控相同 **`HUB_BRIDGE_TOKEN`**。 6. 子代理 **`HOST=127.0.0.1`**;防火墙勿对公网开放 `15200`~`15203`、各 `APP_PORT`。 7. **复盘/实例外链**:`HUB_PUBLIC_ORIGIN=https://你的域名` 或内网 IP;否则其它设备点「复盘」会跳到 `127.0.0.1`。 **说明**:HTTPS 域名与 HTTP `内网IP:5100` Cookie **不共用**;内网访问 IP 需在 IP 地址再登录一次(见 [常见问题.md](./常见问题.md) §2.1)。 --- ## 九、环境变量(中控 `.env`) | 变量 | 默认 | 说明 | |------|------|------| | `HUB_HOST` | `0.0.0.0` | 监听地址 | | `HUB_PORT` | `5100` | 端口 | | `HUB_DISABLED_IDS` | `1` | 强制关闭的账户 id(OKX) | | `HUB_TRUST_LAN` | `true` | 私网可访问;仅本机可 `false` | | `HUB_PUBLIC_ORIGIN` | 空 | 浏览器用复盘链接;如 `http://192.168.1.100`(**内网其它电脑访问中控时建议设置**) | | `HUB_BRIDGE_TOKEN` | 空 | 与四实例一致;公网建议配置 | | `HUB_USERNAME` | `admin` | Web 登录用户名 | | `HUB_PASSWORD` | 空 | 非空即启用登录 | | `HUB_SESSION_SECRET` | — | 会话签名 | | `HUB_COOKIE_SECURE` | `false` | HTTPS 反代建议 `true` | | `HUB_SESSION_DAYS` | `7` | 登录保持天数 | 本地联调、实例 `APP_AUTH_DISABLED=true` 时可不配 `HUB_BRIDGE_TOKEN`;本机不设 `HUB_PASSWORD` 则无需登录页。 --- ## 十、升级与回滚 ```bash cd /opt/crypto_monitor git pull cd manual_trading_hub bash scripts/fix_hub_deps.sh bash scripts/verify_hub_deploy.sh pm2 restart ecosystem.config.cjs # 若只改了中控:pm2 restart manual-trading-hub ``` - **`hub_settings.json`**、**`.env`** 不在 Git 中,`git pull` 不会覆盖。 - 升级前可备份:`cp hub_settings.json hub_settings.json.bak`、`cp .env .env.bak`。 **升级后自检**:`curl -s http://127.0.0.1:5100/api/ping` 须含 `"trade_ui":false`。若仍见 `api_trade_key` 报错,说明代码未更新或未重启,见 [常见问题.md](./常见问题.md) §1。 --- ## 十一、故障排查(速查) **完整实录**见 **[常见问题.md](./常见问题.md)**。 | 现象 | 处理 | |------|------| | PM2 启动后立刻退出 | `pm2 logs manual-trading-hub`;检查 `.venv`、`.env`、`run_hub.sh` | | `api_trade_key` / `python-multipart` | `git pull` → `bash scripts/fix_hub_deps.sh` → `verify_hub_deploy.sh` → 重启 hub | | `verify` ping 解析失败 | hub 未起:`pm2 restart manual-trading-hub` | | 余额显示 — | agent 未加载 `.env`;`fix_env_crlf.sh`;`run_agent.sh` | | agent `$'\r': command not found` | `bash scripts/fix_env_crlf.sh` | | 监控无持仓 | `curl http://127.0.0.1:15200/status` | | 无关键位 / 401 | 启动 Flask;核对 `HUB_BRIDGE_TOKEN` / `hub_bridge` | | 域名能登、IP 不能登 | 见常见问题 §2.1(Cookie / HTTP vs HTTPS) | | 公网访问中控 403 | 反代到 `127.0.0.1:5100`,勿公网直连 5100 | | 改 `.env` 不生效 | `pm2 restart manual-trading-hub` | --- ## 十二、其它常驻方式 - **screen**:`scripts/start_hub_screen.sh` / `stop_hub_screen.sh` - **systemd**:`scripts/example-systemd/manual-hub.service.example`(复制并改路径) 与 PM2 **二选一** 即可,避免同一端口启动两份 hub。 --- ## 十三、安全清单 - [ ] 公网仅暴露反代端口,不暴露 Flask/agent 端口 - [ ] 已设 `HUB_USERNAME` + `HUB_PASSWORD`(中控 Web 登录) - [ ] HTTPS 反代已设 `HUB_COOKIE_SECURE=true` 且传递 `X-Forwarded-Proto` - [ ] 公网已配置 `HUB_BRIDGE_TOKEN` + 实例关闭 `APP_AUTH_DISABLED` - [ ] API Key 最小权限;交易所 IP 白名单 - [ ] 已告知操作人员「全局全平」不可撤销;中控**不在网页下单** --- ## 十四、文档索引 | 文档 | 内容 | |------|------| | [使用说明.md](./使用说明.md) | 功能、页面、API、环境变量 | | [常见问题.md](./常见问题.md) | 故障实录 | | [README.md](./README.md) | 速览 | | [.env.example](./.env.example) | 环境变量模板 | | [scripts/后台运行-Ubuntu.md](./scripts/后台运行-Ubuntu.md) | screen / systemd | | `scripts/fix_hub_deps.sh` | 安装依赖 | | `scripts/verify_hub_deploy.sh` | 部署验收 | | `scripts/fix_env_crlf.sh` | 修复 .env 换行 |