Skip to content

fix(pm2): 避免 Homebrew keg-only Node 被误判为 nvm 版本导致 daemon 无法启动 - #737

Merged
deepcoldy merged 1 commit into
deepcoldy:masterfrom
BoYanZh:fix/pm2-homebrew-node-at-interpreter
Aug 7, 2026
Merged

fix(pm2): 避免 Homebrew keg-only Node 被误判为 nvm 版本导致 daemon 无法启动#737
deepcoldy merged 1 commit into
deepcoldy:masterfrom
BoYanZh:fix/pm2-homebrew-node-at-interpreter

Conversation

@BoYanZh

@BoYanZh BoYanZh commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

pm2(>=6, lib/Common.js)会把任何包含子串 node@ 的 interpreter 路径当作 nvm 版本句柄,尝试 nvm install <后缀>。当 botmux 装在 Homebrew keg-only Node 下时,process.execPath 形如 /home/linuxbrew/.linuxbrew/Cellar/node@22/22.23.1/bin/node,pm2 会把它误读成版本号 22/22.23.1/bin/node,于是每次 botmux start/restart 都失败:

[PM2] Installing Node v22/22.23.1/bin/node
Version '22/22.23.1/bin/node' not found

keg-only formula 没有不带 @ 的可用路径可交给 pm2(Cellar/、opt/、以及非默认的 bin/ 软链都含 node@)。因此本 PR 不改指向别的二进制,而是在 ~/.botmux 下物化一条不带 @ 的稳定软链(node-interpreter),它解析到的仍是启动本 CLI 的同一个 Node(版本一致 → node-pty 等原生模块照常),再把这条软链作为 pm2 interpreter 传入。execPath 变化时(如 Homebrew 补丁升级)软链会刷新,任何 fs 错误则回退到原始 execPath。非 Homebrew 安装不受影响 —— execPath 原样返回。

影响面

仅改 pm2 启动层(src/cli.ts 的 ecosystem 生成)。daemon 每个 bot app 与 dashboard 共用同一安全 interpreter,start/restart/start-bot 三条生成 ecosystem 的路径均覆盖;PTY/Tmux、普通/话题/adopt/restore 会话逻辑及各 CLI 适配器均未改动。Windows 普通路径走 no-op(不触发需权限的 symlink)。

验证

  • 核对 pm2@6.0.14 源码:Common.js:470node@ 判定 + resolveNodeInterpretersplit('@')[1] 取版本,触发链属实。
  • 隔离 HOME + 隔离 PM2_HOME 真启动:用硬链接构造真实 execPath=.../Cellar/node@22/…/bin/node,跑实际 pm2@6.0.14,dashboard 成功 online,ecosystem 与 PM2 jlist 里的 interpreter 都是无 node@~/.botmux/node-interpreter,软链 realpath 回到同一 Node。
  • 合并态(落后 master 71 commit,merge-tree 干净只改 src/cli.ts +47/-3)pnpm build 通过;pnpm test 13232 passed / 24 skipped(唯一失败为无关既有 flaky,单文件重跑通过)。

pm2 (>=6, lib/Common.js) treats any interpreter path containing the
substring `node@` as an nvm version handle and runs `nvm install <suffix>`.
When botmux is installed under a Homebrew keg-only Node, process.execPath is
e.g. /home/linuxbrew/.linuxbrew/Cellar/node@22/22.23.1/bin/node, so pm2
misreads it as version "22/22.23.1/bin/node" and every `botmux start`/
`restart` fails with:

    [PM2] Installing Node v22/22.23.1/bin/node
    Version '22/22.23.1/bin/node' not found

The keg-only formula has no `@`-free path to hand pm2 (Cellar/, opt/, and a
non-default bin/ symlink all contain `node@`), so instead of pointing at a
different binary we materialize a stable `@`-free symlink under ~/.botmux
(node-interpreter) that resolves to the exact same Node, and pass that as the
pm2 interpreter. The symlink is refreshed when execPath changes (e.g. a
Homebrew patch bump) and we fall back to the raw execPath on any fs error.
Non-Homebrew installs are unaffected — execPath is returned verbatim.

Co-authored-by: TRAE CLI <noreply@bytedance.com>
@deepcoldy

Copy link
Copy Markdown
Owner

PR准备好的话记得点:Ready for review

@BoYanZh
BoYanZh marked this pull request as ready for review August 7, 2026 05:10
@BoYanZh
BoYanZh requested a review from deepcoldy as a code owner August 7, 2026 05:10

@deepcoldy deepcoldy left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码复核通过:pm2 keg-only node@ 误判 nvm 的修复定位准确,软链方案版本一致且 fallback 保守,影响面限于 pm2 启动层。合并态 build + test 绿,隔离环境真跑 pm2 验证 dashboard online。合并时用中文标题+正文。

@deepcoldy
deepcoldy merged commit 75d86d0 into deepcoldy:master Aug 7, 2026
@deepcoldy deepcoldy changed the title fix(pm2): avoid nvm misdetection of Homebrew keg-only node interpreter fix(pm2): 避免 Homebrew keg-only Node 被误判为 nvm 版本导致 daemon 无法启动 Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants