From cb9c8f24e86aa8d4f557abf1878b996d33ebe2d5 Mon Sep 17 00:00:00 2001 From: yangxuan Date: Wed, 16 Sep 2026 16:29:49 +0800 Subject: [PATCH] =?UTF-8?q?docs(perf):=20P0-1=20=E8=A1=A5=E5=85=85?= =?UTF-8?q?=E4=B8=89=E7=A7=8D=E5=9C=BA=E6=99=AF=E5=AE=9E=E6=B5=8B=E5=B7=AE?= =?UTF-8?q?=E5=BC=82=E4=B8=8E=E5=8C=85=E8=A3=85=E8=84=9A=E6=9C=AC=E8=90=BD?= =?UTF-8?q?=E5=9C=B0=E6=96=B9=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 经实测澄清(此前表述不够精确): - 场景① 非交互 ssh 裸调 → openclaw: command not found(nvm 未加载则 openclaw 不在 PATH) - 场景② PATH 有 openclaw 但 Node 是 22 → 报 node:sqlite 准入错误并拒跑 - 场景③ 交互式 shell(PATH 含 v26)→ 正常 - 关键机制: openclaw 入口自带运行时准入+自动重试,PATH 里存在合格 Node (24.16+/26.1+) 时会自动改用其重跑,仅在 PATH 无合格 Node 时才拒跑 - 补充: 交互式用 ~/.local/bin/openclaw 包装脚本;非交互场景不加载 ~/.profile 故包装脚本不生效,须显式 source nvm.sh 或用绝对路径 --- docs/openclaw-API响应性能分析与优化.md | 60 ++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/docs/openclaw-API响应性能分析与优化.md b/docs/openclaw-API响应性能分析与优化.md index 22134d7..64e2e26 100644 --- a/docs/openclaw-API响应性能分析与优化.md +++ b/docs/openclaw-API响应性能分析与优化.md @@ -141,7 +141,7 @@ openclaw 的 agent 是 ReAct 式循环:**模型判断 → 调工具 → 结果 | 模型请求 `timeoutMs` | `undefined` | 日志中 `timeoutMs=undefined`,**模型 HTTP 请求无显式超时**;挂住时只能靠 `agents.defaults.timeoutSeconds=3600`(1 小时)兜底 | | `agents.defaults.maxConcurrent` | `2` | 单 agent 并发上限 2(11 个 agent 共用同一 gateway 进程) | | `tools.profile` | `full` | 全量工具集,工具越多模型越容易多轮试探 | -| CLI 运行时 | Node **22.23.1** | 非交互 shell 的 PATH 不含 nvm,`node` 落到系统 `/usr/bin/node`(22),导致 `openclaw models list` **直接报错拒跑**(详见 §4 建议 P0-1) | +| CLI 运行时 | Node **22.23.1**(系统默认) | 非交互 shell 的 PATH 不含 nvm:轻则 `openclaw: command not found`,重则因 Node 22 触发 `node:sqlite` 准入拒跑。详见 §3 的 P0-1(含包装脚本已落地方案) | --- @@ -153,27 +153,69 @@ openclaw 的 agent 是 ReAct 式循环:**模型判断 → 调工具 → 结果 **现象**:`openclaw models list` 报 `Node 22.23.1: node:sqlite truncates TEXT at embedded NUL (nodejs/node#61954); use 24.16+/26.1+` + **根因(2026-09-16 核实)**:系统级 `/usr/bin/node` 是 **v22.23.1**;nvm 的 26.8.2 只在 `~/.nvm/versions/node/v26.8.2/bin/`。**非交互式 SSH(或任何未加载 nvm 的 shell)PATH 不含 nvm 目录**,于是 `node` 落到 `/usr/bin/node` = 22: ``` -$ ssh bk02 'echo $PATH' → /home/yangxuan/.cargo/bin:/usr/local/bin:/usr/bin:/bin:... +$ ssh bk02 'echo $PATH' → /home/yangxuan/.cargo/bin:/usr/local/bin:/usr/bin:/bin:... (0 处含 .nvm) $ ssh bk02 'node -v' → v22.23.1 ← 落到系统 node $ ssh bk02 '~/.nvm/versions/node/v26.8.2/bin/node -v' → v26.8.2 ``` > 与 `.nvmrc` **无关**(已验证 `~/.openclaw/.nvmrc`、`~/deepseek-harness/.nvmrc` 均不存在)。已确认 `nvm alias default` 本就是 `26`——**问题只在 PATH 未加载 nvm**。 -**动作**:凡脚本 / 非交互调用 openclaw,都必须先加载 nvm 或用绝对路径,不要裸调 `node`: +#### 三种场景的行为差异(实测,别再混为一谈) + +| 场景 | 命令 | 实测结果 | +|---|---|---| +| **① 非交互 ssh 裸调** | `ssh bk02 'openclaw models list'` | **`openclaw: command not found`** —— nvm 未加载,连 openclaw 都不在 PATH(路径是 `~/.nvm/versions/node/v26.8.2/bin/openclaw`) | +| **② PATH 里有 openclaw 但 Node 是 22** | `env -i PATH=/usr/bin:/bin openclaw models list` | **报上面那条 `Node 22.23.1: node:sqlite ...` 并拒跑** | +| **③ 交互式 shell**(已加载 nvm,PATH 含 v26 目录) | `openclaw models list` | **正常输出** | + +**关键机制**:openclaw 入口自带**运行时准入 + 自动重试**。当 `#!/usr/bin/env node` 拿到不合格的 Node,而 **PATH 里还存在合格版本(24.16+/26.1+)时,它会自动改用那个 node 重跑**: + +``` +$ openclaw: Retrying with "/home/yangxuan/.nvm/versions/node/v26.8.2/bin/node" + (PATH; current Node failed runtime admission) ← 只是警告,不失败 +$ openclaw: Node 22.23.1: node:sqlite ... use 24.16+/26.1+ ← PATH 无合格 Node 时才拒跑 +``` + +所以**判定标准是「PATH 里有没有合格的 Node」,不是「默认 node 是几」**。 + +#### 动作 + +**交互式使用**(日常最常用)——建一个包装脚本,一劳永逸,不必每次记得 `nvm use`: ```bash -export NVM_DIR=$HOME/.nvm; . $NVM_DIR/nvm.sh # 交互式登录先做(系统说明 §0 已要求) -node -v # 期望 v26.8.2 -openclaw models list --provider deepseek # 期望能正常列出 - -# 非交互/脚本场景:直接给绝对路径,绕开 PATH -~/.nvm/versions/node/v26.8.2/bin/node --version +mkdir -p ~/.local/bin +cp ~/.openclaw/scripts/bin/openclaw ~/.local/bin/openclaw # 仓库内已留存副本 +chmod +x ~/.local/bin/openclaw +openclaw models list --provider deepseek # 期望正常列出 ``` +包装脚本内容(固定绝对路径,绕开 PATH 解析): + +```sh +#!/bin/sh +exec "/home/yangxuan/.nvm/versions/node/v26.8.2/bin/node" \ + "/home/yangxuan/.nvm/versions/node/v26.8.2/lib/node_modules/openclaw/openclaw.mjs" "$@" +``` + +**非交互 / 脚本 / cron / systemd**——这些场景**不加载 `~/.profile`,所以 `~/.local/bin` 也不在 PATH**,包装脚本不生效,必须显式加载 nvm 或用绝对路径: + +```bash +# 方式一:先加载 nvm(推荐,之后 openclaw/node 都正确) +export NVM_DIR=$HOME/.nvm; . $NVM_DIR/nvm.sh +node -v # 期望 v26.8.2 +openclaw models list --provider deepseek + +# 方式二:只用绝对路径(不依赖 shell 初始化) +~/.nvm/versions/node/v26.8.2/bin/node --version +~/.nvm/versions/node/v26.8.2/bin/openclaw models list +``` + +> systemd 服务不受影响:`openclaw-gateway.service` 的 `ExecStart` 写的就是 nvm 26 的绝对路径。 + ### P0-2 减少工具循环轮次(针对 94.6%,收益最大) 轮次是延迟的乘数:**每减少一轮,省下「一次模型往返 + 一次工具等待」(实测中位 6 秒)**。