OpenClaw 更新失败怎么救、回滚分几层、卸载要清掉哪些目录
更新一个常驻后台的网关服务,和更新一个命令行小工具不是一回事。OpenClaw 的 openclaw update 要同时动三样东西:磁盘上的代码包、被 launchd/systemd/计划任务托管的服务单元、以及 ~/.openclaw 里那堆 SQLite 状态库。任何一步断在中间,你面对的都不是”重装一遍”这么简单。
真正会在半夜把人叫醒的问题有三个:更新跑到一半失败了,现在这台机器处于什么状态、该用哪条命令收尾;新版本能跑但行为不对,回滚要不要连状态一起退回去;以及决定不用了,除了 npm rm -g,还有哪些目录和服务单元留在机器上。
安装方式怎么选、四个发布通道分别是什么语义,前面那篇安装方式对比已经讲过。这篇只谈出事之后的处置。
更新中断了,先判断断在哪一步
openclaw update 的动作顺序是:检测安装类型(npm、pnpm、Bun 或 git)→ 拉取目标版本 → 运行 openclaw doctor → 重启网关。分界线在包替换那一刻。
对 npm 全局安装,OpenClaw 的替换过程是有暂存的:先把目标版本装进一个临时 npm prefix,候选包在 preinstall 阶段校验宿主机的 Node 版本,通过之后 OpenClaw 才去核对打包出来的 dist 清单,最后把干净的包树整体换进真正的全局 prefix。清单里故意不包含一个打包的 completion guard,它只在 preinstall 成功之后才被移除——这样即使生命周期脚本被跳过,也会在换入之前失败。npm 12 及以上,更新器只批准候选 OpenClaw 自己的生命周期脚本,传递依赖的脚本仍然被拦住。这套做法要防的是 npm 把新包直接覆盖到旧包的残留文件上。安装命令失败时,OpenClaw 会带 --omit=optional 重试一次,这对原生可选依赖编译不过的机器有用。
关键判断落在这里:如果 openclaw update 是在 npm 包安装阶段之后失败的,不要反复重跑更新器,改成重跑安装器。安装器不调用更新器,它直接执行全局包安装,能把一个更新到一半的 npm 安装救回来。
curl -fsSL https://openclaw.ai/install.sh | bash -s -- --install-method npm
要把恢复钉死在某个版本或 dist-tag 上,加 --version:
curl -fsSL https://openclaw.ai/install.sh | bash -s -- --install-method npm --version <version-or-dist-tag>
另一类高频失败是权限。root 拥有的 Linux 系统级全局安装,openclaw update 会以 EACCES 失败。官方给的恢复路径是让网关全程停着,用拥有那个 root 全局 prefix 的系统 npm 手动替换(把 /usr/bin/npm 换成你机器上真正的那个),完事再把服务装回去:
openclaw gateway stop
sudo /usr/bin/npm i -g openclaw@latest
openclaw gateway install --force
openclaw gateway restart
pnpm 用户有一个专门的坑:如果是 pnpm 11 装的 OpenClaw 2026.7.1,需要手动跑一次 pnpm add -g openclaw@latest。那个版本早于 pnpm 11 的隔离式全局包布局,它的更新器可能把另一个 npm 安装误认成正在运行的 CLI。之后的版本会保留 pnpm 归属、跟随替换后的包根,并在检测到可用的 pnpm 报告了另一个全局根或另一个大版本、或调用方包已成孤儿、或那里不止一个活跃 OpenClaw 安装时,停在改动之前。还有一种情况更新器会主动罢工:OpenClaw 和别的包共享同一个 pnpm 11 全局安装组时,它不会去改这个组,需要你手动更新那个逗号分隔的原始组,以免捎带破坏同组包和构建策略。
诊断手段方面,openclaw update 没有 --verbose(那是安装器的),能用的是 --dry-run 预览计划动作、--json 拿结构化结果、openclaw update status --json 看通道与可用性状态。包更新前的磁盘空间预检是尽力而为的:空间不足只产生一条带路径的警告,不会拦住更新,因为配额、快照和网络卷在检查之后还会变,最终以包管理器安装和安装后校验为准。
还有一条容易忽略的纪律:手动用包管理器更新受托管的安装时,必须先停网关。包管理器是原地替换文件的,跑着的网关可能在替换过程中去加载核心或插件文件;替换完再重启网关让它认到新安装。
自动更新那侧的失败也有痕迹可循:每一次失败的 apply 都会结束当前更新活动,避免界面一直停在 Updating。托管服务交接开始之后的失败会额外记进重启哨兵,网关回来之后浮出来;没有托管的直接失败留在运行中的网关日志里。事故处置期间想按住自动更新器别再抢着装新版本,在网关环境里设 OPENCLAW_NO_AUTO_UPDATE=1。
回滚是两层,先只退代码
文档把回滚明确拆成两层,顺序不能颠倒:
| 层 | 做什么 | 代价 | 什么时候才用 |
|---|---|---|---|
| 第一层:代码回滚 | 装回旧版 OpenClaw 代码,状态原封不动 | 基本无损 | 默认从这里开始 |
| 第二层:状态回滚 | 恢复更新前的状态快照 | 丢掉备份之后的全部变更 | 仅当旧代码读不了迁移后的配置或数据库 |
包安装的代码回滚,先列出已发布版本,再预览、再执行:
npm view openclaw versions --json
openclaw update --tag <known-good-version> --dry-run
openclaw update --tag <known-good-version>
用 openclaw update --tag 而不是直接调包管理器,是因为前者会识别出这是降级并要求确认,会对目标版本跑托管插件收敛和兼容性检查,会刷新服务元数据、重启网关并校验实际运行版本。一个例外:如果存下来的通道是 extended-stable,要写成 --channel stable --tag <known-good-version>,因为一次性的精确 tag 不能和 extended-stable 选择器组合。
包更新的激活是先暂存再校验的,所以文件系统换入或命令 shim 替换失败时,OpenClaw 会自动把旧包放回来。但要注意边界:换入成功之后才出现的网关健康检查失败,不会触发第二次自动替换,它只会报出上一个版本号和手动回滚指引。CLI 更新通道整个不可用时,就用拥有当前网关的那个包管理器和安装作用域手动来:
openclaw gateway stop
npm i -g openclaw@<known-good-version>
openclaw gateway install --force
openclaw gateway restart
源码 checkout 的回滚走 git:
git fetch --all --tags
git checkout --detach <known-good-tag-or-commit>
pnpm install && pnpm build
openclaw gateway restart
回到最新是 git checkout main && git pull。git 更新启动之后,如果依赖安装、构建、UI 构建或 doctor 失败,更新器会自动把 checkout 退回之前的分支和 SHA;只有你主动挑一个更老的提交时才需要手动 checkout。
还有一个跨版本的专项:会话存储从文件迁到 SQLite 之后再往回降级,要先用当前 CLI 把归档的旧版 transcript 产物恢复出来。
openclaw gateway stop
openclaw doctor --session-sqlite restore --session-sqlite-all-agents
这条命令不会删 SQLite 数据,但迁移之后新建的会话只存在于 SQLite 里,老运行时看不见它们。会话本身在重启前后如何存续,可以对照重启恢复机制那篇。
回滚做完,用这一串核对结果:openclaw --version、openclaw health、openclaw plugins list --json、openclaw gateway status --deep --json、openclaw doctor --lint --json。doctor 输出怎么逐项对号入座,见 doctor 体检输出解读。
备份能覆盖什么、覆盖不到什么
先记一条硬边界:openclaw update 只保留一份自动的更新前配置副本,它不创建完整的状态恢复点。重大更新之前想要恢复点,得自己显式建:
mkdir -p ~/Backups/openclaw
openclaw backup create --output ~/Backups/openclaw --verify
归档的 manifest 会记下 OpenClaw 版本和纳入备份的源路径。归档里可以含凭据、认证档案和渠道状态,权限要按 owner-only 存放,保护级别和活状态目录一致。想要连便携归档故意跳过的易变产物一起拿到,只能停掉网关、用平台自己的文件系统/卷/虚拟机快照做逐字节恢复点。
另一条别踩的红线:永远不要直接拷贝活着的 .sqlite、-wal、-shm、-journal 文件当备份。网关运行时这些库一直在写,裸文件拷贝可能撕裂或损坏。官方给的四条路子分工很清楚:
| 路径 | 命令 | 适合 |
|---|---|---|
| 完整便携归档 | openclaw backup create | 更新、重置、卸载、换机之前 |
| 单库快照 | openclaw backup sqlite create | 紧凑、带 SHA-256 可复验 |
| 版本化增量 | openclaw backup git create | 按内容提交,无变化不产生提交 |
| 连续复制 | Litestream | 只把变化的页传出去 |
恢复这一侧是刻意做成显式的,没有任何东西会原地覆盖活状态。openclaw backup restore <archive> --target <fresh-directory> 只把文件铺进一个全新的暂存目录,目标必须不存在或为空,非空会被拒绝,失败的解压会清掉半成品,而且没有 force、没有原地模式。激活是单独的离线步骤:停网关 → 把恢复出来的状态资产移到位,或把 OPENCLAW_STATE_DIR 指过去 → 跑 openclaw doctor → 再重启。
状态恢复的代价文档说得很直白——它是时间旅行。带棘轮状态的消息渠道凭据(WhatsApp 尤其明显)可能失步、需要重新链接;审批以及投递/去重状态也会一起退回去,恢复之后先复查待处理的审批再放网关跑。插件的 node_modules 树不在归档里,激活后要跑 openclaw plugins update <id> 或 openclaw plugins install <spec> --force 重装,再用 openclaw skills list 或起一次 agent 会话,让被省略的 plugin-skills/ 符号链接索引按当前插件元数据重建。插件这套机制的全貌见插件体系。跨版本恢复还有一步前置:先用 openclaw database preflight 对目标版本做预检。
卸载要清的不止一个 npm 包
CLI 还在的话,用内置卸载器最省事,先预览:
openclaw uninstall --dry-run --all
openclaw uninstall
它把要删的东西拆成四个 scope:--service(服务单元)、--state(状态与配置)、--workspace(工作区)、--app(macOS 应用),--all 是四个全选。这里有个默认行为值得记住:openclaw uninstall --state 会刻意保留配置过的工作区目录,包括默认的 ~/.openclaw/workspace;而你手动 rm -rf 状态目录是没有这个保护的。所以走手动路线之前,先把想留的工作区移出状态目录。
手动清理的完整顺序是:openclaw gateway stop 停服务 → openclaw gateway uninstall 卸掉服务单元 → 决定工作区去留 → rm -rf "${OPENCLAW_STATE_DIR:-$HOME/.openclaw}" 删状态与配置(如果把 OPENCLAW_CONFIG_PATH 指到了状态目录之外,那个文件要另外删)→ 删状态目录之外的工作区(仅当你也想删掉它的 agent 文件)→ 按当初的方式移除 CLI(npm rm -g openclaw / pnpm remove -g openclaw / bun remove -g openclaw)→ 装过 macOS 应用的话删掉 /Applications/OpenClaw.app。用过 profile(--profile / OPENCLAW_PROFILE)的,状态目录默认是 ~/.openclaw-<profile>,每个都要重复;远程模式下状态目录在网关主机上,那台机器也得走一遍。
比较麻烦的是另一种局面:CLI 已经没了,服务还在跑。这时候按平台手动摘:
# macOS(launchd),默认标签 ai.openclaw.gateway
launchctl bootout gui/$UID/ai.openclaw.gateway
rm -f ~/Library/LaunchAgents/ai.openclaw.gateway.plist
# Linux(systemd 用户单元)
systemctl --user disable --now openclaw-gateway.service
rm -f ~/.config/systemd/user/openclaw-gateway.service
systemctl --user daemon-reload
Windows 上是计划任务,默认任务名 OpenClaw Gateway,它拉起的是状态目录下一个无窗口的 gateway.vbs,后者再去跑 gateway.cmd,两个文件都要删:
schtasks /Delete /F /TN "OpenClaw Gateway"
Remove-Item -Force "$env:USERPROFILE\.openclaw\gateway.cmd" -ErrorAction SilentlyContinue
Remove-Item -Force "$env:USERPROFILE\.openclaw\gateway.vbs" -ErrorAction SilentlyContinue
用了 profile 就把任务名和这两个文件换成对应的 ~\.openclaw-<profile>。从很老的版本升上来的机器上,可能还留着改名前的 clawdbot-gateway.service,openclaw uninstall 和 openclaw gateway uninstall 会自动检测并移除它。源码 checkout 的卸载顺序别搞反:先卸服务,再删仓库目录,最后清状态和工作区——仓库删了服务单元就没法用 CLI 卸了。
这套办法覆盖不到的地方
容器不走这条线。Docker、Podman、Kubernetes 是镜像替换,官方另有升级容器镜像的说明;网关会在就绪之前跑启动安全的升级工作,挂载的状态需要人工修复时它会直接退出。
自动更新活动会打断终端会话。活动等当前工作跑完后启动一分钟倒计时,倒计时一旦开始,新来的工作不会重置它;15 分钟硬截止会在还有工作时也强制更新。开着的终端会话既不会推迟倒计时也不会推迟应用,网关重启会结束这些进程内的 PTY,而且事后不做恢复。
备份的运维部分基本没有内置托管:快照仓库就是本地目录,调度、上传、保留策略、开机恢复都留给操作者自己实现。openclaw backup enable 需要网关可达才能启用或禁用调度,没有本地兜底调度器。Litestream 只复制数据库字节,配置、凭据文件和工作区还得靠上面那几条基于文件的路径。归档校验也别指望太多:openclaw backup verify 检查的是归档结构和载荷布局,它不认证归档来源,也不能让不可信内容变安全——只从你自己创建或确实信任的归档恢复。
最后是回滚这件事本身的限度。文档给的是”装回旧代码”和”恢复旧状态”两条路,但它没有承诺任意版本之间都能来回切。会话 SQLite 迁移就是一个明确的单向门:迁移之后产生的会话,老运行时看不到。所以真正省事的做法还是那句老话——重大更新之前先建一个校验过的恢复点,而不是出事之后再找当时的状态在哪。
延伸阅读
- 从头读起:OpenClaw 架构总览:网关、Agent、渠道、节点、插件五层各管什么,出问题该往哪查
- 本专题共 40 篇,完整分组目录见专题页
- OpenClaw 网关起不来怎么办:锁文件、端口占用与后台进程的三层排查
- OpenClaw 网关出问题先开哪个开关:日志级别、—verbose 与诊断导出包的分工
本文依据 OpenClaw 官方仓库(github.com/openclaw/openclaw)docs/ 下的官方文档整理,核对日 2026-08-17。
我们没有安装或运行过 OpenClaw,因此不涉及界面外观、操作手感与实测耗时的任何描述;
文中的默认值、命令与配置项均为文档口径,不构成对实际运行结果的保证。
该项目迭代很快,请以仓库最新内容为准。接入即时通讯平台前,请自行确认所在平台的规则与合规要求。