docs: 新增 openclaw 升级与维护手册(Node 22→26 / OpenClaw 2026.9.4 / 清理与存储结论)

This commit is contained in:
2026-09-16 10:47:45 +08:00
parent 570165ae3c
commit ebc140e2d1
+302
View File
@@ -0,0 +1,302 @@
# openclaw 升级与维护运维手册(bk02)
> 主机:**bk02** / `xuan-asus-nj`Debian 12 bookworm`192.168.3.14`tailscale `100.115.195.192`
> 组件:OpenClaw Gateway(用户级 systemd+ tailscale serveHTTPS 入口)
> 版本:OpenClaw `2026.8.1` → **`2026.9.4`**;运行 Node `/usr/bin/node 22.23.1` → **nvm `v26.8.2`**
> 更新:2026-09-16(本次为实测记录,含命令、证据与踩坑)
>
> ⚠️ 本文不写明文口令。凭据位置见 §7。
---
## 1. 架构总览
```
浏览器 / App
↓ https://bk02.baiji-algieba.ts.net tailscale serve443 终止 TLS
↓ 转发到本机回环
bk02: node 进程 127.0.0.1:18789 openclaw gateway
存储:~/.openclaw/state/openclaw.sqlite(共享状态)
~/.openclaw/agents/<id>/agent/openclaw-agent.sqlite(每 agent 会话/记忆)
```
| 项 | 值 |
|---|---|
| 服务单元 | `openclaw-gateway.service`**用户级** systemd`systemctl --user` |
| 监听 | `127.0.0.1:18789`+ `[::1]:18789`),不直接对外 |
| 对外入口 | `gateway.tailscale.mode = serve``https://bk02.baiji-algieba.ts.net` |
| 启动命令 | `/home/yangxuan/.nvm/versions/node/v26.8.2/bin/node --max-old-space-size=3913 <openclaw>/dist/index.js gateway --port 18789` |
| 插件 | 8 个 enableddingtalk-connector、feishu、memory-core、ollama、openclaw-weixin、searxng 等 |
| 状态目录 | `~/.openclaw`(本次清理前 2.6G,清理后 1.5G) |
---
## 2. 本次升级:2026.8.1 → 2026.9.4
### 2.1 阻塞点:Node 版本(先踩后解)
`openclaw update` 直接拒绝,原文:
```
Node 22.23.1 at /usr/bin/node is too old for openclaw@2026.9.4.
The requested package requires >=24.16.0 <25 || >=26.1.0
```
关键点:**gateway 服务实际用的是系统 `/usr/bin/node`22.23.1**,而 nvm 里的 `v25.9.0` **也不被支持**(要求排除整个 25.x)。
| Node | 版本 | 满足 2026.8.1 | 满足 2026.9.4 |
|---|---|---|---|
| 系统 `/usr/bin/node`(升级前在用) | 22.23.1 | ✅ | ❌ |
| nvm | v25.9.0 | ✅ | ❌(25.x 被排除) |
| nvm | **v26.8.2**(本次采用) | — | ✅ |
### 2.2 执行步骤(可复现)
```bash
# 1) 装 Node 26(用户级,不动系统 node —— 同机还有 VS Code Server 等依赖它)
export NVM_DIR=$HOME/.nvm; . $NVM_DIR/nvm.sh
nvm install 26 # → v26.8.2
nvm alias default 26 # 让新 shell 与 gateway 版本一致
# 2) 全局安装新版本(必须放行 install scripts,否则原生模块不构建,见 §3.1)
nvm use 26
npm i -g openclaw@2026.9.4 \
--allow-scripts=openclaw,@google/genai,koffi,tree-sitter-bash,protobufjs
# 3) 用官方命令重建服务定义,让 gateway 切到 Node 26
systemctl --user stop openclaw-gateway
openclaw daemon install # 自动检测并替换不支持的 Node,见下
```
`openclaw daemon install` 会自己发现并修掉旧 Node,原文输出:
```
Node 22.23.1: node:sqlite truncates TEXT at embedded NUL (nodejs/node#61954); use 24.16+/26.1+
Replacing unsupported Gateway service Node 22.23.1 (/usr/bin/node) with ~/.nvm/versions/node/v26.8.2/bin/node
Previous unit backed up to: ~/.config/systemd/user/openclaw-gateway.service.bak
```
> **顺带修掉一个数据隐患**Node 22 的 `node:sqlite` 存在「TEXT 遇内嵌 NUL 被截断」的已知 bugnodejs/node#61954)。
> 升级前每条含空字符的消息都可能被静默截断 —— 换到 Node 26 后不再发生(历史已截断的数据无法自动还原)。
```bash
# 4) 同步插件到同版本(doctor 会逐个点名)
openclaw plugins update feishu
openclaw plugins update @openclaw/searxng-plugin@2026.9.4
openclaw plugins update @openclaw/deepseek-provider@2026.9.4
openclaw gateway restart
```
### 2.3 验收证据(实测)
| 验证项 | 结果 |
|---|---|
| 版本 | `OpenClaw 2026.9.4 (3a9d69d)` |
| 运行 Node | `/proc/<pid>/exe → v26.8.2/bin/node` |
| 服务状态 | `active``NRestarts=0` |
| 启动日志 | `[gateway] ready``[tailscale] serve enabled: https://bk02.baiji-algieba.ts.net/` |
| 插件 | 6→8 个加载,`feishu`/`searxng`/`deepseek``2026.9.4` |
| 远端首页 | HTTP/2 **200**ttfb ≈ **0.139s** |
| 前端资源 | 压缩后 **348KB**(原始 1387KBBrotli),9 个资源并发 **0.160.79s** |
| WS 端点 | **200** |
| 数据完整性 | 12 个 agent 全在、36 个 SQLite 库、自动完成 v16/v17 状态迁移 |
---
## 3. 踩坑清单(复现时必读)
### 3.1 npm 11 会静默拦下 install scripts
首次 `npm i -g openclaw@2026.9.4` 虽然「成功」,但这些脚本**没执行**:
```
openclaw (postinstall: postinstall-bundled-plugins.mjs)
koffi (install: cnoke.cjs --prebuild) ← 原生模块
tree-sitter-bash (install: node-gyp-build) ← 原生模块
protobufjs / @google/genai
```
**必须带 `--allow-scripts=...` 重装**,否则运行时才暴露缺模块。
### 3.2 服务里的 Node 路径是硬编码的
`ExecStart` 记录的是绝对路径与具体 Node 版本目录。手工改 systemd 容易漏(`PATH` 环境变量里也含版本号),**优先用 `openclaw daemon install` 重建**,它会连带更新 `PATH`、保留原有 `Environment=` 注入。
### 3.3 两个命令需要显式 `--force`
| 命令 | 不加 force 的表现 |
|---|---|
| `openclaw gateway stop` | 拒绝:「This stops the operator's running gateway service… re-run with `--force`」 |
| `openclaw plugins uninstall <id>` | 交互确认;非交互环境需 `--force`**没有** `--non-interactive` 这个参数) |
---
## 4. 存储结论:只能用 SQLite(不能换 PG/MySQL
官方文档 `llms-full.txt` 原文:
> **SQLite remains the supported runtime store.** Preparation for PostgreSQL should improve the existing store owners and their tests **before adding a driver or configuration option**.
即 PG 支持**连驱动和配置项都还没有**,仅处于前瞻设计阶段。旁证:
| 检查 | 结果 |
|---|---|
| 官方文档 `mysql` / `mariadb` 命中 | **0 次 / 0 次** |
| 官方文档 `postgres` 命中 | 6 次,全在「Preparing for another database backend」一节 |
| 代码里 PostgreSQL/MySQL 字样来源 | **SQL 语法高亮方言**CodeMirror / kysely dialect)与报错文案,**非存储后端** |
| 实际驱动 | `node:sqlite`Node 内置,无外部依赖) |
| 存储位置 | `state/openclaw.sqlite` + `agents/<id>/agent/openclaw-agent.sqlite`(共 36 个库) |
**但是**:本机 docker 里的 pgsql / mysql **可以作为 agent 的工具数据源**(配置里 `"MySQL":{"enabled":true}` + `sql-toolkit`),这与「openclaw 自身存储」是两层,互不影响。
> 结论:想提升存储层,**升级 Node 比换数据库更实在**(§2.2 的 NUL 截断 bug 就是典型)。
---
## 5. 清理历史版本配置 / 缓存 / 残留
### 5.1 官方清理入口
| 目标 | 命令 | 备注 |
|---|---|---|
| 迁移「回滚原始文件」 | `openclaw update cleanup --dry-run` → 停机后 `openclaw update cleanup` | 官方专用于清理 upgrade 残留 |
| agent 库 VACUUM | `openclaw doctor --session-sqlite compact --session-sqlite-all-agents` | 需停机 |
| 共享状态库压缩 | `openclaw doctor --state-sqlite compact --json` | 需停机,会设置 `auto_vacuum=INCREMENTAL` |
| 列表/删除历史会话 | `openclaw sessions` | |
| 继承文件迁移 | `openclaw doctor --fix` | 会归档为 `<源>.migrated.<sha256>.<id>` |
| 卸载插件(含目录) | `openclaw plugins uninstall <id> --force` | |
停机维护的官方推荐顺序:
```bash
openclaw backup create --verify # 先备份(必做)
openclaw gateway stop --force
openclaw doctor --session-sqlite compact --session-sqlite-all-agents
openclaw doctor --state-sqlite compact --json
openclaw gateway start
```
### 5.2 本次清理成效(实测)
| 项目 | 手段 | 释放 |
|---|---|---|
| npm 缓存 | `npm cache clean --force` | **1.7 GB** |
| 旧版 Node 25(含 openclaw 2026.8.1 | `nvm uninstall 25.9.0` | **1.5 GB** |
| `memory-lancedb`disabled 插件) | `openclaw plugins uninstall memory-lancedb --force` | **950 MB** |
| 旧版本 UI 资源缓存 | 核对当前 build 引用后删旧 hash 目录 | **28 MB** |
| SQLite 空闲页 | 上述两个 compact | 2.9 MB |
| 重复 skill 目录 | 全量比对后移出 | 20 KB |
| 验证失败的备份包 | 删除 | 378 MB |
**根分区 26G/109G (26%) → 24G/109G (23%)**`~/.openclaw` 2.6G → 1.5G。
共享状态库 compact 实测输出(可作判据基线):
```json
{ "before": { "autoVacuum": 0, "dbSizeBytes": 15339520, "freelistPages": 435 },
"after": { "autoVacuum": 2, "dbSizeBytes": 12771328, "freelistPages": 0 },
"reclaimedBytes": 2568192, "integrityCheck": "ok" }
```
### 5.3 不能动的东西(官方设计,删了会出问题)
| 路径 | 为什么保留 |
|---|---|
| `openclaw.json.bak` + `.bak.1`~`.bak.4` | 官方**配置备份环**:任何配置写入都会轮转(`--fix` 亦然) |
| `openclaw.json.last-good` | 解析失败时的自动恢复源 |
| `openclaw.json.pre-update` | 升级前备份 |
| `agents/*/agent/*.sqlite` | 当前会话/记忆数据 |
| `~/.openclaw/.git` | 配置备份仓库(见 §6 |
### 5.4 边界:`update cleanup` 拒绝清理的那 525MB
`agents/*/session-sqlite-import-archive/` 下有 654 个 `*.imported-*`(约 **525MB**),是 2026-08-31 会话从 JSONL 迁入 SQLite 时的归档。官方 cleanup **拒绝清理**
```
Candidates: 0 bytes; verification required: 550782825; protected: 0; blocked: 0
原因: historical-manifest-without-import-proof
```
- `doctor --session-sqlite validate` / `dry-run` 均返回 `0 target(s)`:没有待导入的遗留源
- `compact` 报告 `archived-unreferenced-jsonl=0`openclaw 认为这些归档**仍被清单引用**
- 独立验证:`session_transcript_archives` 表用 **`archive_blob` BLOB 把内容存在库内**,全表**不引用外部文件路径** ⇒ 这些 JSONL 确如文档所述「**not runtime fallbacks**」(非运行时依赖),**删除不影响运行**,但会**永久失去降级回旧 JSONL 版本的能力**
**结论:暂不清理**(保留 525MB 换历史恢复能力)。若将来确认不需要降级,可手动删除该目录 —— 但官方不背书,删前务必备份迁移凭证 `session-sqlite-migration-runs/`
---
## 6. 备份、配置仓库与回滚
### 6.1 备份
```bash
openclaw backup create --verify --output ~/openclaw-backups
```
⚠️ 若 workspace 下存在**仅大小写不同**的重复目录(本次为 `skills/Obsidian``skills/obsidian`),`--verify` 会因 *portable path collision* **失败**。处理方式:
```bash
diff -r skills/obsidian skills/Obsidian # 确认内容一致(本次仅 .clawhub/origin.json 的安装元数据不同)
mv skills/Obsidian ~/openclaw-backups/removed-skills/ # 移出而非删除
```
### 6.2 配置仓库(Gitea
| 项 | 值 |
|---|---|
| 仓库 | `~/.openclaw`(工作区内的 git 仓库,分支 `314` |
| remote | `https://gitea.climbcube.cn/yangxuan/openclaw-config.git` |
| 自动提交 | `auto-commit-config.sh`,每 6 小时 `git add -A` + commit + push,无变更则跳过 |
| 提交信息 | `auto: sync OpenClaw config <时间>` / `auto: agent DB backup <日期>` |
**体积治理(本次)**`.git` 曾达 199M / 249 次提交。根因**不是** SQLite`.gitignore` 已忽略 `*.sqlite`),而是 workspace 里的大数据文件被自动提交并推送:
```
90.2 MB workspace-juaner/data/私聊_王芳.json
36.9 MB workspace-juaner/data/私聊_王芳.jsonl
11.7 MB agents/*/session-sqlite-import-archive/*.imported-*
```
⚠️ **隐私提示**`.gitignore` 原未忽略 `workspace-*/data/`,导致私聊内容进入 git 历史并推送到 Gitea。
已加固 `~/.openclaw/.gitignore`
```gitignore
workspace-*/data/
agents/*/session-sqlite-import-archive/
```
`git rm -r --cached`(保留本地文件)使既有大文件脱离跟踪,后续提交不再增长。**历史重写(filter-repo)未做**,如需彻底清除需另行评估(会与 remote 冲突,需 force push)。
### 6.3 回滚
```bash
# 服务定义
cp ~/.config/systemd/user/openclaw-gateway.service.bak ~/.config/systemd/user/openclaw-gateway.service
nvm install 25.9.0 && nvm exec 25.9.0 npm i -g openclaw@2026.8.1
systemctl --user daemon-reload && systemctl --user restart openclaw-gateway
```
> 注意:本次已删除 nvm `v25.9.0`1.5G)与 `memory-lancedb`**回滚需重新下载**`~/openclaw-backups/` 内的验证备份(351MB,不含 workspace)仍可恢复数据。
---
## 7. 凭据与密钥位置(不含明文)
| 用途 | 位置 |
|---|---|
| gateway 认证 | `~/.openclaw/openclaw.json``gateway.auth`password 模式) |
| 机主登录 | 由机主掌握;本机 `~` 用户 `yangxuan` |
| 模型 / 渠道密钥 | `~/.openclaw/.env``openclaw.json``secrets` 段(systemd 以 `OPENCLAW_SERVICE_MANAGED_ENV_KEYS` 注入) |
| 备份包 | `~/openclaw-backups/*.tar.gz`(含凭据,勿外发) |
---
## 8. 遗留观察点
1. **`.git` 仍为 199M** —— 索引清理只阻止未来增长,历史未重写。
2. **525MB 迁移归档保留**(§5.4),如需释放需人工决策。
3. **skill 重名冲突 5 条**`weather`/`obsidian`/`blogwatcher`/`mcporter`/`baidu-text-translate`):workspace 覆盖 bundled,属**设计内优先级行为**,非错误,可不管。
4. **gateway 重启频率**:升级前曾出现单日 5 次重启(2026-09-15),重启后 20 秒内 RPC 会达 1.5–4.4s(冷启动),稳态 0 次慢调用。若再遇「打开很慢」,先查是否落在重启窗口。
5. **链路**wit01 ↔ bk02 走 DERP 中继(`MappingVariesByDestIP: true`,对称 NAT),实测首屏 0.160.79s,服务端本身 < 10ms。