|
|
@@ -0,0 +1,210 @@
|
|
|
+# 容器状态上报 · 标准部署包(后续所有容器统一走这套)
|
|
|
+
|
|
|
+| 字段 | 值 |
|
|
|
+|---|---|
|
|
|
+| 文档编号 | 标准包-20261020-reporter |
|
|
|
+| 版本 | v1.0 |
|
|
|
+| 创建日期 | 2026-10-20 |
|
|
|
+| 适用 | **新容器上线 / 现有容器修复 / 格式排查** |
|
|
|
+| 配套 | `reporter字段规范-20261020.md`(字段契约)、`容器初始化流程优化建议-20261020.md`(初始化流程)|
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 零、为什么要有这个包
|
|
|
+
|
|
|
+2026-10-20 全平台盘点 54 个容器,`balance` 字段出现**三种写法**:
|
|
|
+
|
|
|
+| 写法 | 容器数 | 来源 |
|
|
|
+|---|---|---|
|
|
|
+| `remainCny` / `source` / `totalCalls` | **7** | 原版 `status-report.py` ✅ |
|
|
|
+| `remainRmb` / `remainUsd` | 1(`agent-node`)| 更老的 v2 脚本 |
|
|
|
+| **`cny` / `source`** | **1**(`agent-node-lj-test`)| **容器自己写的复刻脚本** ❌ |
|
|
|
+
|
|
|
+**每多一个"自己写"的,就多一种格式。** 这个包的目的就是**堵住这个口子**。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 一、三步走(新容器上线)
|
|
|
+
|
|
|
+```
|
|
|
+① 部署原版脚本(不让人自己写)
|
|
|
+ ↓
|
|
|
+② 配 4 个环境变量
|
|
|
+ ↓
|
|
|
+③ 跑验收清单(9 条断言)
|
|
|
+```
|
|
|
+
|
|
|
+### ① 部署原版脚本
|
|
|
+
|
|
|
+**路径固定**(不要再换):
|
|
|
+
|
|
|
+```
|
|
|
+/opt/data/git-repos/agent-status-reporter/scripts/status-report.py
|
|
|
+/opt/data/git-repos/agent-status-reporter/state/ ← 状态快照与失败队列
|
|
|
+```
|
|
|
+
|
|
|
+**脚本来源优先级**(按顺序试):
|
|
|
+
|
|
|
+| 顺序 | 方式 | 命令 |
|
|
|
+|---|---|---|
|
|
|
+| 1 | **从同宿主正常容器拷**(最快) | `docker cp <正常容器>:/opt/data/git-repos/agent-status-reporter/scripts/status-report.py <目标容器>:/opt/data/git-repos/agent-status-reporter/scripts/` |
|
|
|
+| 2 | 从平台仓库拉 | 见 `部署说明书.md` |
|
|
|
+| 3 | 由项目侧提供 | `E:\work\fmode-app\docs\03-interface\reporter-v3\status-report.py`(v11,49410 字节)|
|
|
|
+
|
|
|
+> 🔴 **不要自己重写**。原版 1100 行,覆盖了:变化检测、失败队列、token 自愈、任务残留清理、
|
|
|
+> 官方 channel 探测、usage 聚合。自己复刻必然漏掉其中一部分 —— 这次踩的就是这个坑。
|
|
|
+
|
|
|
+### ② 配环境变量
|
|
|
+
|
|
|
+只改 `/opt/data/.env`(**改前先备份 `.env.bak-<时间戳>`**):
|
|
|
+
|
|
|
+```bash
|
|
|
+# 🔴 必填 4 项
|
|
|
+AGENT_ID=<容器名,如 agent-node-xxx> # 缺省会退化成 hostname → agent not found
|
|
|
+FMODE_SESSION_TOKEN=<主人的 sessionToken> # 决定容器归属哪个账号
|
|
|
+AGENT_FUNCTION_ID=xlosi3m46q # 🔴 填错会走到 OBS 上传,数据进不去
|
|
|
+WECOM_BOT_ID=<企微 BotID> # 有企微通道时必填
|
|
|
+
|
|
|
+# 可选
|
|
|
+AGENT_STATUS_HEARTBEAT=30 # 心跳间隔秒
|
|
|
+AGENT_STATUS_ENABLED=true
|
|
|
+```
|
|
|
+
|
|
|
+> ⚠️ **企微配置不在 `.env`** —— 在 Hermes 的 `config.yaml` 的 `platforms.wecom` 段。
|
|
|
+> 实测坑:只读 env 会导致 `wecom:false` + `botId` 为空。原版脚本已支持从 `config.yaml` 解析。
|
|
|
+
|
|
|
+### ③ 常驻
|
|
|
+
|
|
|
+容器通常**没有 crontab**(实测多容器均无)。三种方式按优先级:
|
|
|
+
|
|
|
+```bash
|
|
|
+# 方式 A · s6 服务(如果容器用 s6,与其他服务一致,最稳)
|
|
|
+# 方式 B · 宿主 cron 统一调度
|
|
|
+* * * * * root docker exec <容器> python3 /opt/data/.../status-report.py >/dev/null 2>&1
|
|
|
+
|
|
|
+# 方式 C · 容器内循环(兜底;脚本自带 daemon 模式更优)
|
|
|
+nohup sh -c 'while true; do python3 /opt/data/.../status-report.py; sleep 30; done' >> /tmp/x.log 2>&1 &
|
|
|
+```
|
|
|
+
|
|
|
+> 原版脚本自带 `daemon_loop()` 模式,优先用它而不是外层循环。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 二、验收清单(9 条,缺一不可)
|
|
|
+
|
|
|
+```bash
|
|
|
+# 上报一次后回读
|
|
|
+curl -s 'https://server.fmode.cn/parse/classes/FmodeAgent?where={"agentId":"<你的agentId>"}' \
|
|
|
+ -H 'X-Parse-Application-Id: ncloudmaster'
|
|
|
+```
|
|
|
+
|
|
|
+| # | 断言 | 通过标准 | 常见错法 |
|
|
|
+|---|---|---|---|
|
|
|
+| 1 | `host.cpuPercent` | 数字,0~100 | 发 `cpuLoad1`(负载不是占用率)|
|
|
|
+| 2 | `host.memPercent` | 数字,0~100 | — |
|
|
|
+| 3 | `host.diskPercent` | 数字,0~100 | — |
|
|
|
+| 4 | `channels` **是对象** | `{...}` | 发数组 `["wecom"]` |
|
|
|
+| 5 | `channels.matrix` | 与真实通道一致 | 只读 env 声明,假亮 |
|
|
|
+| 6 | `channels.wecomBotId` | 等于 `WECOM_BOT_ID` | 从 env 读不到(实际在 config.yaml)|
|
|
|
+| 7 | `heartbeatAt` | 60 秒内 | 发裸字符串(需 `{"__type":"Date","iso":...}`)|
|
|
|
+| 8 | `usage.totalTokens` | > 0 | 未接 `state.db` |
|
|
|
+| 9 | `balance.remainCny` | 有数字 | 发 `cny`(现已由云函数兜底,但**不该依赖**)|
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 三、三条纪律(这次踩坑换来的)
|
|
|
+
|
|
|
+### 纪律 1 · 查运行态,不查路径
|
|
|
+
|
|
|
+```
|
|
|
+❌ find / -name "status-report.py" → 找不到就说"没部署"
|
|
|
+✅ ps aux | grep -i status → 拿到 pid
|
|
|
+ cat /proc/<pid>/cmdline → 看实际跑的是哪个文件
|
|
|
+ ls -l /proc/<pid>/cwd → 实际工作目录
|
|
|
+```
|
|
|
+
|
|
|
+「找不到文件」≠「进程没在跑」。
|
|
|
+
|
|
|
+### 纪律 2 · 调用失败 ≠ 凭据失效
|
|
|
+
|
|
|
+| 现象 | 容易误判 | 实际 |
|
|
|
+|---|---|---|
|
|
|
+| `Bearer` 头 → 401 | token 过期了 | 调用姿势不对 |
|
|
|
+| body `{"sessionToken":...}` → 200 | — | ✅ 正确姿势 |
|
|
|
+
|
|
|
+**先换姿势,再怀疑令牌。**
|
|
|
+
|
|
|
+### 纪律 3 · 每个数字都要回读,不许自算
|
|
|
+
|
|
|
+```
|
|
|
+❌ 自己算一遍 cpuPercent=16.4,然后报"已验证"
|
|
|
+✅ 上报后 op=get 读回原文,把字面值贴进报告
|
|
|
+```
|
|
|
+
|
|
|
+实测教训:容器连续两轮报「已验证」,但库里根本没那个键、值也对不上。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 四、平台侧兜底(已上线)
|
|
|
+
|
|
|
+云函数 `xlosi3m46q` **v0.1.3**(2026-10-20)已加 `balance` 键名归一:
|
|
|
+
|
|
|
+```
|
|
|
+cny / remainRmb / remain → 自动补 remainCny(原键保留,只增不改)
|
|
|
+```
|
|
|
+
|
|
|
+**效果**:以后容器即使写错键名,App 也能显示余额。
|
|
|
+
|
|
|
+⚠️ **但这是兜底不是许可** —— 新容器仍应按 §二 第 9 条报 `remainCny`。
|
|
|
+兜底只能救「已经写错」的,救不了「没上报」的(如 `usage` 压根没发,变不出来)。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 五、新容器上线检查表(可直接贴给容器)
|
|
|
+
|
|
|
+```markdown
|
|
|
+【容器状态上报 · 标准接入】
|
|
|
+
|
|
|
+一、部署
|
|
|
+ mkdir -p /opt/data/git-repos/agent-status-reporter/{scripts,state}
|
|
|
+ 从同宿主正常容器 docker cp 原版 status-report.py(不要自己写)
|
|
|
+
|
|
|
+二、配置 /opt/data/.env(先备份)
|
|
|
+ AGENT_ID=<容器名>
|
|
|
+ FMODE_SESSION_TOKEN=<主人 token>
|
|
|
+ AGENT_FUNCTION_ID=xlosi3m46q
|
|
|
+ WECOM_BOT_ID=<企微 BotID>
|
|
|
+
|
|
|
+三、常驻(crontab 一般不可用,用 s6 或 daemon 模式)
|
|
|
+
|
|
|
+四、验收(回读平台值,逐条断言,缺一不可)
|
|
|
+ □ host.cpuPercent 0~100
|
|
|
+ □ host.memPercent / diskPercent
|
|
|
+ □ channels 是对象不是数组
|
|
|
+ □ channels.matrix 与真实状态一致
|
|
|
+ □ channels.wecomBotId 匹配
|
|
|
+ □ heartbeatAt 60 秒内
|
|
|
+ □ usage.totalTokens > 0
|
|
|
+ □ balance.remainCny 有值
|
|
|
+
|
|
|
+五、纪律
|
|
|
+ · 用 ps/proc 查进程,不用 find 查文件
|
|
|
+ · 调用失败先换姿势,再怀疑 token
|
|
|
+ · 报告里的每个数字必须是回读原文的字面值
|
|
|
+
|
|
|
+报告格式:
|
|
|
+REPORTER-OK agentId=<...>
|
|
|
+cpuPercent=<回读> memPercent=<回读> diskPercent=<回读>
|
|
|
+channels=<对象/数组> matrix=<true/false>
|
|
|
+heartbeatAt=<回读> usage.totalTokens=<回读> balance.remainCny=<回读>
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 六、关联文档
|
|
|
+
|
|
|
+- `docs/03-interface/reporter字段规范-20261020.md` —— 逐字段契约(**改造前必读**)
|
|
|
+- `docs/03-interface/容器初始化流程优化建议-20261020.md` —— 初始化流程与排查方法论
|
|
|
+- `docs/03-interface/reporter部署方案-20261020.md` —— 单容器部署细节
|
|
|
+- 原版脚本:`E:\work\fmode-app\docs\03-interface\reporter-v3\status-report.py`(v11)
|
|
|
+- 云函数备份:`.local-backup/xlosi3m46q-v0.1.3.js`(当前线上),`-v0.1.2.js`(回滚基线)
|