OpenClaw 网关运维总入口
本机(Windows + Git Bash)OpenClaw 网关的排障与恢复。先读第 1 节做分诊,再按需打开对应 references 分册,不要一次读全部。
1. 症状分诊表(第一步永远看这里)
| 现象 | 首要怀疑 | 去哪一节 |
|---|---|---|
| 微信端"Something went wrong" / 无响应 | 会话写锁或上下文溢出 | §4 → references/locks.md |
三端口全无 / health 报 os error 10061 |
网关死了,且守护任务可能早已静默失效 | §3 |
cron 报 failed / timed out |
模型链路 or 工具错误 | §5 → references/cron.md |
cron 报 All models failed (N): ...402/429 |
账户欠费 + 会话层 model 钉子 | §6 → references/models-billing.md |
cron 报 delivery not-delivered / 微信没收到 |
微信 context_token 陈旧 |
§7 → references/weixin-delivery.md |
| 网关 health 正常但到处 EPERM / readonly database | 网关跑在沙箱里 | §2 铁律一 → references/lifecycle.md |
| 模型请求 TLS/socket 断连 | 上游网络瞬断(先排除 Clash) | references/network.md |
| 仪表盘 WebSocket 连不上 | gateway.auth token 模式 |
references/gateway-auth.md |
微信发 PDF 报 Exec failed: run node inline script |
pdf 工具未启用 | references/tools-pdf.md |
2. 三条铁律(违反任一条,后面全是白干)
铁律一:网关必须跑在沙箱外。
从 WorkBuddy Bash 工具(含 run_in_background)拉起的网关会继承沙箱限制,表现为 health 正常但全面带病:EPERM: open AGENTS.md、attempt to write a readonly database、模型请求 network connection error(还会被误记为 billing 熔断)。
唯一可靠常驻手段 = Windows 计划任务(拉起后进程 ppid=1,脱离一切会话)。详见 references/lifecycle.md。
铁律二:换模型/换 provider 必须查三层,少一层就复发。
① 全局 openclaw.json → agents.defaults.model.primary/fallbacks
② 会话 agents/main/sessions/sessions.json 的 model / modelProvider / authProfileOverride
③ transcript sessions/<uuid>.jsonl 的 {"type":"model_change"} 事件
会话层会压过全局配置,而 cron 会话(agent:main:cron:<jobId>)最容易被钉死。详见 references/models-billing.md。
铁律三:cron agentTurn 对工具错误零容忍。
运行中任何一次 source=tool, severity=error(哪怕只是某个 curl exit 1)都会让整次 run 判定失败并丢弃已生成的正文、不投递。所以要保证 agent 全程零工具错误 —— 给足配套工具(exec 必须配 process),并在 prompt 里明令禁止容易失败的动作。详见 references/cron.md。
3. 标准恢复流程(网关整体死亡)
# 1) 确认死透了 + 死了多久
netstat -ano | grep LISTENING | grep -E ":18789|:18888|:18899"
ls -t /c/Users/Administrator/AppData/Local/Temp/openclaw/*.log | head -3 # 日志日期 = 死亡时间
tail -20 /c/Users/Administrator/AppData/Local/Temp/openclaw/gateway_wrapper.log # 找 ^C
# 2) 查守护任务——State=Ready 不代表在干活!
Get-ScheduledTaskInfo -TaskName 'OpenClawGatewayGuard' | Select LastRunTime,LastTaskResult
# 0 = 正常
# 2147942402 = 0x80070002 可执行文件不存在 ← 最常见,见下
Start-ScheduledTask -TaskName 'OpenClawGatewayGuard' # 立即重建全部服务
LastTaskResult = 2147942402 的经典成因:WorkBuddy 的 PortableGit 升级会删除旧版本目录,而任务动作硬编码了旧 versions/<old>/bin/bash.exe。修动作:
$act = New-ScheduledTaskAction -Execute 'D:\Program Files\新建文件夹\WorkBuddy\resources\vendor\PortableGit\bin\bash.exe' -Argument 'C:\Users\Administrator\.openclaw\gateway-guard.sh'
Set-ScheduledTask -TaskName 'OpenClawGatewayGuard' -Action $act
Start-ScheduledTask -TaskName 'OpenClawGatewayGuard'
Get-ScheduledTaskInfo -TaskName 'OpenClawGatewayGuard' # 必须回到 0
> schtasks.exe 在本机黑名单里,但 PS 原生命令 Get/Set/Start-ScheduledTask 不走 schtasks.exe,沙箱不拦。
恢复验证记分卡:三端口 LISTENING → curl /health {"ok":true} → 日志 gateway ready + weixin monitor started → cron 会自动补偿漏掉的运行 → next_run 回归正常时刻。
一键检查:bash scripts/oc_health.sh
4. 会话写锁 / 上下文溢出
错误类型直接决定调参方向:
| 日志特征 | 含义 | 处理 |
|---|---|---|
orphan-self-pid, ageMs 很小 |
Windows 平台自我误判(getProcessStartTime 仅 Linux 支持) |
打 v3 补丁(同 pid 一律不判孤儿) |
session file locked (timeout Nms) |
等锁超时 | 调大 session.writeLock.acquireTimeoutMs |
hold-exceeded, ageMs≈maxHoldMs |
合法持锁超上限(长推理/compaction) | 调大 maxHoldMs(→1800000) |
too-old, hold-exceeded + age 数小时 |
崩溃遗留残留锁 | 删锁 + 重启 |
session file changed while embedded prompt lock was released |
锁释放流程物理损坏 | 重建会话 |
context-overflow-precheck ... overflowTokens=K |
会话历史超模型 contextWindow | 重建会话,或换 256K 模型 |
| 锁 pid=自己、jsonl 停更、turn 早已结束 | releaseHeldLock 泄漏 |
打 v4 补丁;应急删锁 |
上下文窗口速查:deepseek-v4-flash/pro = 131072;kimi-k3 / k2.7-code-highspeed / k2.7-code / k2.6 = 256000。
补丁与重建流程:references/locks.md
5. cron 故障
先判断是哪一层失败:
node scripts/cron_status.js # 最近 10 次 run + job 状态一览
status / error |
层级 | 处置 |
|---|---|---|
timed out (last phase: model-call-started) |
模型无响应 | 换 provider / 调超时,见 references |
timed out,但日志 [model-fetch] response status=200 |
SSE 流后续 hang | 切 Moonshot |
Exec failed: <cmd> (exit 1) / process poll <slug> |
agentTurn 工具错误 | 补 process 工具 + 改 prompt |
interrupted by gateway restart |
watchdog 杀僵尸 session 连带砍掉 cron | 见 references |
All models failed (N) |
计费/会话钉子 | 见 §6 |
status=ok 但 delivery_status≠delivered |
投递层 | 见 §7 |
改 cron 任务配置的唯一正确姿势:权威源是 sqlite state/openclaw.sqlite 的 cron_jobs 表(cron/jobs.json 是迁移残留,不要改)。改 payload_message 时必须同步改 job_json 里的嵌套副本,然后重启 gateway(内存调度器不热读 sqlite)。
测试触发:UPDATE cron_jobs SET next_run_at_ms = Date.now()+75000,然后重启。
全谱案例与判据:references/cron.md
6. 模型 / 计费
看到"候选数少于全局配置的 provider 数"就立刻怀疑会话覆盖 —— All models failed (2) 里的 2 是会话生效的候选数,不是全局候选数。
node scripts/check_model_pins.js # 扫出所有被钉死在某个 provider 的会话
- 查余额:
curl -s https://api.deepseek.com/user/balance -H "Authorization: Bearer <DK>" - 凭据位置:
agents/main/agent/openclaw-agent.sqlite→ 表auth_profile_store(store_key=primary,store_json.profiles.<provider>:manual) - 熔断(cooldown)状态:同库
auth_profile_state → usageStats.<profile>.disabledUntil - 清 provider 熔断 ≠ 清会话覆盖,两件事都要做(10/15→10/16 连续两天在同一坑复发过)
三层修复步骤与验证记分卡:references/models-billing.md
7. 微信投递
成功与失败的响应格式完全不同,写判定脚本时极易搞反:
| 结果 | 响应 |
|---|---|
| 成功 | HTTP 200 + {"message_id": 7503303557188221448}(没有 ret 字段) |
| 失败 | {"ret":-2,"errmsg":"prepare failed"} |
ret=-2 的唯一根因 = context_token 陈旧(openclaw-weixin/accounts/<bot>.context-tokens.json 的 mtime 停更)。
解锁方式只有一种:用户主动在微信给 bot 发一条消息,上游才会下发新 token。ilink/bot/getconfig 返回的 typing_ticket 不能替代(实测仍 ret=-2)。
# 轮询等 token 刷新,检测到即自动补发
node scripts/send_weixin.js # 自动读最新 token + sync.json 的 userId
node scripts/send_weixin.js --watch --text-file briefing.txt
细节、sendmessage 协议字段、历史踩坑:references/weixin-delivery.md
8. 目录 / 端口速查
| 项 | 位置 |
|---|---|
| openclaw 包 | C:/Users/Administrator/.workbuddy/binaries/node/versions/22.22.3/node_modules/openclaw/ |
| Node | 同目录 node.exe;node_clone.exe(火绒按 node.exe 名拦截时的副本,升级后需重新复制) |
| 配置 | ~/.openclaw/openclaw.json(改前必备份 cp ... .bak.$(date +%Y%m%d-%H%M%S)) |
| 守护脚本 | ~/.openclaw/gateway-guard.sh(幂等:health 好就退,死了清锁+拉起三件套) |
| 日志 | %TEMP%/openclaw/openclaw-YYYY-MM-DD.log、gateway_wrapper.log、ds_proxy.log、weixin_proxy.log |
| 会话 | ~/.openclaw/agents/main/sessions/(sessions.json + <uuid>.jsonl + .lock) |
| 数据库 | ~/.openclaw/state/openclaw.sqlite(cron_jobs / cron_run_logs / gateway_boot_lifecycle) |
| 端口 | 18789 网关 / 18888 微信代理 / 18899 DeepSeek 代理 |
| 健康 | curl -s http://127.0.0.1:18789/health → {"ok":true,"status":"live"} |
本机被安全策略拦掉的启动通道(别浪费时间试):schtasks.exe、Start-Process、Invoke-CimMethod Win32_Process Create、wmic、reg.exe、explorer.exe <cmd>(2026-10 起失效)、沙箱内 nohup(调用结束即回收)。可用:PS 原生 *-ScheduledTask、run_in_background(仅过渡)。
9. 参考分册索引
| 文件 | 何时读 |
|---|---|
references/lifecycle.md |
启动/重启/常驻/沙箱污染/进程收敛/EPERM readonly database/openclaw 包丢失重装 |
references/locks.md |
会话锁全谱、orphan-self-pid / v3 / v3.1 / v4 补丁代码、turn 悬挂、watchdog 僵尸 session、会话重建流程 |
references/cron.md |
cron 全部失败模式、kind-dune 纠偏、双时间预算、payload 修改、手动补跑 |
references/models-billing.md |
402/429、欠费、熔断、会话钉子、maxTokens 截断、contextWindow、failover 配置 |
references/weixin-delivery.md |
context_token 机制、sendmessage 协议、typing_ticket 无效、补发流程 |
references/network.md |
Clash 排查结论(已排除)、TLS 瞬断、ds_proxy 存废、web_fetch fake-ip、fetch_news.py 兜底 |
references/gateway-auth.md |
仪表盘连不上、token 模式转 none、Telegram channel 接入 |
references/tools-pdf.md |
PDF 工具启用(三层配置)、clawpdf 验证 |
10. 脚本索引
| 脚本 | 用途 |
|---|---|
scripts/oc_health.sh |
三端口 + health + 进程归属 + cron next_run 一把梭 |
scripts/cron_status.js |
读 sqlite 输出所有 job 状态与最近 run logs |
scripts/check_model_pins.js |
扫 sessions.json,列出被 provider 钉死/残留的会话 |
scripts/send_weixin.js |
直发微信(自动读最新 context_token),支持 --watch 轮询等刷新 |
> 脚本里的 node 一律用绝对路径 C:/Users/Administrator/.workbuddy/binaries/node/versions/22.22.3/node.exe(PATH 里没有)。