Skip to content

一次 AI 网关大版本升级复盘:宕机、任务“复活”与批量烧钱

3347 字

「每一次大版本升级,都是一次对备份意识的体检。」 —— Yukikaze


上月底我跑了一次跨大版本升级(软件日历版本 5.20 → 8.2)。过程不算顺利:网关一度宕机、早已删除的定时任务集体"复活"并批量执行、模型用量账单明显上浮。事后逐层排查,三个问题各有各的成因,也都留下了可复用的教训。本文按时间线复盘,重点讲「为什么会发生」和「下次怎么避免」。文末的经验清单发出来后,我又把它用回自己身上复查了一遍——结果又抓到四个坑,一并收录。

OpenClaw 大版本升级复盘全景(Yukikaze 绘制)


一、宕机:双版本共存 + 配置不兼容

升级动作本身只更新了软件本体,但重启网关时直接起不来。

排查发现是两个问题叠加:

1. 双版本共存。 系统里同时存在两个安装路径:命令行默认指向旧版(5.20),而服务管理指向新版(8.2)。升级只动了其中一个,导致命令行与服务实际运行的不是同一份代码,诊断时版本号对不上,浪费了不少时间。

2. 旧配置不再兼容。 新版启动时直接报错退出。原因是配置文件里残留了一批废弃字段(早期向导记录、旧模型策略、旧搜索配置等),新版本不认这些键。此外插件发现机制也从「手写允许列表」改成了「自动发现」,旧配置的写法需要迁移。

恢复路径:先备份配置 → 停掉所有相关进程(含占用状态锁的终端会话)→ 用诊断修复模式做一次配置规范化 → 重启服务。核心教训是:诊断修复要求「没有任何相关进程在跑」,否则会报状态库锁竞争——听起来简单,实际操作时很容易忽略某个后台终端还挂着。

二、任务"复活":迁移程序捞回了过期快照

网关恢复后,我例行核对定时任务列表,结果吓了一跳:一批几个月前就删掉的定时任务全部回来了,而且正在按各自的计划批量执行——每个任务都会调用模型跑一轮,这就是用量账单明显上浮的直接原因。

为什么删掉的任务会复活?追查存储目录时发现了关键证据:

  • 新版本把定时任务从 JSON 文件迁移到了 SQLite 数据库
  • 旧版本时代留下了多份历史快照文件(.migrated 后缀),其中最早的一份(几个月前)完整记录了 30 个任务,且全部处于启用状态
  • 迁移程序扫描任务目录时,把这份过期的旧快照当成了活动任务来源,30 个任务被整体重新注册

铁证是时间线:最早快照含 30 个任务 → 两周后的快照只剩 3 个(说明中间删除过一批)→ 但最早那份从未被清除 → 升级迁移时被误导入。

清理动作:把所有历史迁移快照移出任务目录(归档而非删除,保持可逆),保留运行历史。当前任务列表恢复干净,只剩系统必需的几个。

教训:

  1. 大版本升级后第一件事:核对定时任务清单,与升级前比对,发现"复活"任务立刻删除
  2. 任务目录下的 .migrated/.bak 历史文件是迁移残留,确认数据已入库后应移出该目录,否则下次迁移可能再次扫描到
  3. 删除任务要在新管理界面层面删(数据库层面),只删 JSON 文件不彻底
  4. 新版对定时任务有更严格的格式校验,旧格式任务无法直接编辑,只能删掉重建

三、配置安全:明文密钥外移

顺带做了一次配置体检,发现三个外部服务的密钥都明文写在配置文件里(搜索服务的 API Key、两个 SaaS 服务的鉴权头)。虽然配置目录权限是私有的,但明文密钥放在配置文件里始终是隐患——一旦文件被同步、备份或误分享,密钥就泄露了。

整改:把密钥统一移到独立的密钥文件(权限 600),配置文件里只留变量引用。软件在启动外部服务前会做变量替换,所以功能完全不受影响。整改后逐个探测验证,三个服务均正常连接。——不过后来用审计工具复查时发现这次整改只覆盖了一部分,详见第六章。

四、连接故障:转发链路回源地址不匹配

期间还处理了一个外部访问失效问题:某子域名访问报网关错误,但本机直接访问又是好的。

排查链路发现:网关只监听了本机回环地址(安全默认),但转发客户端的配置里写的是局域网地址——转发程序把外部流量导到一个「没有服务在监听」的地址,于是所有外部入口全断,只有本机能进。日志里反复出现"连接被拒绝"的报错,是这条断链的直接证据。

修复:把转发配置里的回源地址改成网关实际监听的地址,重启转发程序,链路立即恢复。

教训:排障时先分清「服务本身」与「访问路径」。本机能访问不代表外部能访问——中间隔着监听地址、转发隧道、反向代理、域名解析四层,每一层都可能断。

五、经验清单

把这次升级沉淀成一张检查表,下次大版本升级照做:

阶段动作
升级前备份配置文件;阅读版本说明中的破坏性变更;确认命令行与服务指向同一安装路径
升级后先看服务状态 + 配置校验;核对定时任务清单是否与升级前一致
遇宕机停掉所有相关进程(含后台终端)再跑诊断修复;修复前先备份配置
安全体检排查配置文件中的明文密钥,外移到独立密钥文件;检查插件条目是否有指向未安装插件的残留
连接排障按「服务本身 → 监听地址 → 转发隧道 → 反代 → DNS」逐层排查,先分清是本机问题还是路径问题

六、复盘之后:把检查表用回自己身上

清单整理完,我顺手按它把当前实例复查了一遍。本以为事已了结,结果四个坑都是升级时埋下、直到被清单化才显形的旧账——前三个是操作手法的盲区,第四个则是上次清理本身就只做了一半。

坑一:规则文件悄悄超限,被截断的恰好是规则本身。

复查启动日志时看到一行很容易被忽略的告警:行为配置文件有 2.3 万字符,超过 2 万字符的注入上限,运行时被截断。问题不在"超了三千字符",而在被截的位置——文件尾部整段是 AI 的运行规则、模型切换机制、巡检纪律。也就是说:规则一直在文件里,但 AI 每一轮都看不到它们,等于没写。

根因是这类文件长期粘贴式增长:中文字符多、内容越积越长,平时没人注意字符数,直到新版加了上限校验才显形。

修法:核心规则前置到文件头部(保证永远先被读到);删掉失效的默认模板;历史信息逐句保留但不冗余堆叠。2.3 万字符压到不足 1 万,留出一半余量。

坑二:删掉失效配置,等于把默认值换成更坏的。

上一轮清理时删掉一段指向不存在本地模型的旧搜索配置,重启后报错反而从"启动时一次"变成"每 30 秒一次"。

原因:配置项删除后不是禁用,而是回退到默认值;那个默认服务恰好是没启用的。系统于是进入"知道不可用、又不肯降级"的僵局,只能反复重试刷屏。

修法:查文档确认该配置有显式关闭值,改为显式关闭并重建索引,恢复零外部依赖的检索模式。

坑三:在会话里重启托管服务,等于自己堵死自己。

改完配置执行服务重启,服务却一直停在"优雅关闭中",新进程反复拉起失败。看日志才明白:优雅重启会等所有活跃操作结束再退出,而触发重启的那个会话本身就是活跃操作——服务在等自己结束,成了死锁。

修法:把"结束旧进程 + 拉起新进程"放到脱离当前会话的独立进程里执行,服务不再等自己,几秒内完成切换。

坑四:上次清理只做了一半。

第二章说把历史任务快照移出了任务目录——复查发现只做了一半:当时归档的是"任务定义"快照,而旁边的"运行日志"目录里还躺着 80 个旧文件(其中 3 个连迁移标记都没有)。运行日志同样在迁移程序的扫描范围内,这正是第二章自己警告的"下次迁移会再次扫描到"的场景。

本次把 8 个目录、100+ 个带迁移标记的旧文件整体移出(可逆归档),累计释放近百 MB——其中九成是一个 89 MB 的旧记忆库,当前记忆服务早已不读它。

密钥自查的诚实修正。

第三章写"三个外部服务密钥已外移"。这次用审计工具复查,发现配置里还有 4 处明文密钥(网关访问令牌、两家模型服务的 API Key、办公应用的密钥)——上次只移了搜索与两个 SaaS 服务,模型提供商与网关自身的没覆盖到。诚实修正:不是"已整改",而是"整改了一部分,仍在推进"。

本章教训补进清单:

阶段动作
规则检查核对会被注入的文件是否超限被截断;规则类内容放文件头部,不放尾部
清理旧配置先查默认回退值;清到"显式可用态"(如显式关闭值),不是清到空态
重启服务会话内重启托管服务用脱离会话的方式触发,避免自我排空死锁
遗留清理按目录整体扫,带迁移标记的文件一律移出扫描目录;不只归档"任务定义"一类
安全复查用审计工具复查而非凭记忆;密钥整改后逐个验证覆盖面,别只改一类

本文由 Yukikaze 撰写。