关于 smoke-test
smoke-test 是用于检查 gbrain 部署健康状况的技能,在机器或容器重启后运行。它执行核心检查、尝试修复部分本地故障,并支持添加自定义脚本。
主要功能
- 01运行 gbrain 核心健康检查
- 02按需检查 OpenClaw 服务
- 03自动修复部分本地故障
- 04支持用户自定义测试脚本
- 05记录结果并用退出码报告故障
适用场景
- 01机器或容器重启后检查服务
- 02启动脚本中验证部署状态
- 03排查数据库或工作进程故障
- 04添加部署专属检查
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ garrytan/ gbrain --skill smoke-test安装后在 Claude Code 中输入/smoke-test确认已加载。
详细介绍
Smoke Test Skillpack
在任何机器或容器重启之后,或在出现疑似故障时,运行
gbrain smoke-test。
约定
本 Skill 保证:
- 8 项核心测试用于验证重启后 gbrain 的健康状态(若存在 OpenClaw 服务则一并检测;否则跳过)
- 有界的本地故障会在报告前自动修复;worker 修复需显式执行,因为进程拓扑和 shell 任务策略由运营者决定
- 可通过
~/.gbrain/smoke-tests.d/*.sh拖放脚本进行用户扩展 - 结果记录到
/tmp/gbrain-smoke-test.log - 退出码 = 未修复的失败数量(0 = 全部通过)
内置测试
| # | 测试 | 自动修复 |
|---|---|---|
| 1 | Bun 运行时 | 从 bun.sh 安装 |
| 2 | GBrain CLI 可加载 | 重新安装依赖 |
| 3 | GBrain 数据库(通过 gbrain engine status --json 确认引擎身份,然后检查 doctor --json 的 connection 项) | gbrain db-repair --yes,然后重新测试 |
| 4 | GBrain worker 进程 | —(原生 supervisor 状态 + 重复进程检测) |
| 5 | OpenClaw Codex 插件(Zod CJS);若未安装 OpenClaw 则跳过 | npm install zod@4 --force |
| 6 | OpenClaw 网关;若未安装 OpenClaw 则跳过 | —(可能尚未启动) |
| 7 | Embedding API 密钥 | —(检查 .env) |
| 8 | Brain 仓库存在 | — |
用法
命令行
gbrain smoke-test
所有安装均使用此调用方式;它会从已安装的包中解析测试脚本。
从任意启动脚本或登录钩子调用
gbrain smoke-test >> /tmp/bootstrap.log 2>&1
从 OpenClaw 引导流程调用(仅限 OpenClaw 部署)
添加到你的 ensure-services.sh 或同类脚本中:
bash /path/to/gbrain/scripts/smoke-test.sh >> /tmp/bootstrap.log 2>&1
从 Agent 调用
exec: gbrain smoke-test
贡献者注意:在 gbrain 仓库检出目录中,也可以直接运行 bash scripts/smoke-test.sh。
添加自定义测试
在 ~/.gbrain/smoke-tests.d/ 中创建可执行脚本:
# ~/.gbrain/smoke-tests.d/check-redis.sh
#!/bin/bash
redis-cli ping | grep -q PONG
规则:
- 退出码 0 = 通过,非 0 = 失败
- 文件名即测试名称(例如
check-redis.sh对应的测试名为check-redis) - 保持测试快速(每项少于 10 秒)
- 测试按字母顺序执行
添加内置测试(gbrain 贡献者)
本节面向在 gbrain 源码仓库中工作的贡献者。插件安装时脚本为只读,升级时会被覆盖;如果你只是想增加额外检查,请使用上文的 ~/.gbrain/smoke-tests.d/ 拖放脚本。
编辑 scripts/smoke-test.sh,遵循以下模式:
# ── N. [Service Name] ──────────────────────────────────────
if [test condition]; then
pass "[Service Name]"
else
# Auto-fix attempt
[fix command]
if [re-test condition]; then
fixed "[What was fixed]"
pass "[Service Name] (after fix)"
else
fail "[Service Name] — [error detail]"
fi
fi
设计规则:
- 先测试 —— 在确认故障存在之前绝不修复
- 修复后重新测试 —— 验证修复是否生效
- 所有操作设置超时 —— 对任何可能挂起的命令使用
timeout N - 使用辅助函数 ——
pass()、fail()、fixed()、skip() - 修复操作保持幂等 —— 可安全地重复运行
- 优雅跳过 —— 当前置条件缺失时使用
skip(),不要判定为失败
环境变量
| 变量 | 默认值 | 说明 |
|---|---|---|
GBRAIN_SMOKE_LOG | /tmp/gbrain-smoke-test.log | 日志文件路径 |
GBRAIN_DIR_OVERRIDE | (自动检测) | 强制指定 gbrain 安装路径 |
GBRAIN_BUN_PATH | (自动检测) | 强制指定 Bun 可执行文件路径 |
GBRAIN_DATABASE_URL | (来自 .env) | 数据库连接 URL |
GBRAIN_SMOKE_WORKER_PID_FILE | /tmp/gbrain-worker.pid | 旧版裸 worker PID 文件路径 |
OPENCLAW_GATEWAY_PORT | 18789 | 待测试的网关端口 |
GBRAIN_BRAIN_PATH | (因部署而异) | Brain 仓库路径。容器部署默认为 /data/brain;其他情况请设置为你的 brain 仓库路径。未设置时测试 8 会跳过(而非失败)。 |
已知问题及其自动修复
Codex Zod core.cjs 缺失(发现于 2026-04-23)
(仅适用于 OpenClaw 网关部署:此问题涉及 OpenClaw 的 Codex ACP 插件,而非 OpenAI Codex CLI。)
- 症状:
Cannot find module './core.cjs'→ 所有 Codex ACP 会话失败 - 原因: 部分安装中的 Zod v4 npm 包缺少
core.cjs - 自动修复: 在 codex 扩展的 zod 目录中执行
npm install zod@4 --force - 持久性: 容器重启后不会保留(网关会重新安装依赖)
- 这也是为什么冒烟测试必须在每次重启时运行的原因
GBrain Worker 认证失败
- 现象: Worker 无法连接数据库
- 原因:
GBRAIN_DATABASE_URL未传递给 Worker 子进程 - 自动修复: 脚本显式传入
DATABASE_URL和GBRAIN_DATABASE_URL
失败时如何处理
对于任何 gbrain 错误 code、退出码、[AGENT] 代码块或通知代码块,请遵循 Agent 操作员协议。本技能的特定要求如下:
- 退出码 = 未修复的失败数量:逐一报告每项失败的名称及已尝试的修复方法;当有测试被跳过时,绝不能报告全部通过。
- 数据库测试因
GBRAIN_DB_ACCESS标记而失败:运行gbrain db-repair并重新测试;重写级别的修复需要用户同意。 - 嵌入 API 密钥检查失败:此项没有自动修复。告知用户缺少哪个密钥,并说明在设置该密钥之前,搜索仅能使用关键词匹配。
反模式
- ❌ 每个对话轮次都运行冒烟测试。每次容器重启后(或用户要求时)运行一次即可。该脚本开销很小,但并非没有成本。
- ❌ 在用户自定义的 drop-in 中,对任何可能挂起的命令不加
timeout N。一个挂起的 drop-in 会阻塞之后的每次运行。 - ❌ 未先确认检查确实失败就自动修复。
通过 → 检测到失败 → 修复 → 重新测试这一循环是既定约定;跳过重新测试的修复可能在仍然损坏的状态下报告成功。 - ❌ 将
skip当作fail。缺少前置条件(未安装 OpenClaw、未配置 brain 仓库)属于跳过,而非失败。退出码 = 真实失败的数量,而不是跳过的检查项数量。 - ❌ 在用户自定义的 drop-in 中硬编码路径。应读取环境变量(
GBRAIN_DATABASE_URL、HOME等),使脚本能够在容器重建后继续使用。
输出格式
脚本会向标准输出逐项写入一行状态(✅/❌/🔧/⏭️),并在最后输出一行汇总:Results: N/M passed, F auto-fixed, S skipped。结构化的带时间戳日志会追加写入 $GBRAIN_SMOKE_LOG(默认为 /tmp/gbrain-smoke-test.log),便于运行后排查。退出码等于未修复失败的数量(0 = 全部通过,正整数 = 剩余失败数量)。