Skip to content

fix(install): pin node absolute path in MEMORY_TENCENTDB_GATEWAY_CMD#54

Closed
YOMXXX wants to merge 1 commit into
Tencent:mainfrom
YOMXXX:fix/systemd-node-absolute-path
Closed

fix(install): pin node absolute path in MEMORY_TENCENTDB_GATEWAY_CMD#54
YOMXXX wants to merge 1 commit into
Tencent:mainfrom
YOMXXX:fix/systemd-node-absolute-path

Conversation

@YOMXXX
Copy link
Copy Markdown
Contributor

@YOMXXX YOMXXX commented May 18, 2026

Summary | 摘要

修复 #19:install 脚本生成的 `MEMORY_TENCENTDB_GATEWAY_CMD` 用裸 `npx`,systemd 环境下 PATH 不含 nvm/asdf 装的 node → daemon spawn 失败、Hermes 反复日志 "Gateway unreachable"。改为 install 时 resolve node 绝对路径,并用 `node --import tsx/esm` 替代 `npx tsx`。

Fix #19: `MEMORY_TENCENTDB_GATEWAY_CMD` used bare `npx` which fails under systemd (nvm/asdf node not in systemd's minimal PATH). Now resolves node's absolute path at install time and uses Node-native `--import tsx/esm` to remove the runtime PATH dependency.

Root cause

`scripts/install_hermes_memory_tencentdb.sh:229` (before):

```bash
GATEWAY_CMD="sh -c 'cd $TDAI_INSTALL_DIR && exec npx tsx src/gateway/server.ts'"
```

  • 交互 shell:`/.bashrc` 加载 nvm → PATH 含 `/.nvm/versions/node/v*/bin/` → `npx` 找到 → OK
  • systemd service:默认 PATH = `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`,不 source 任何 user shell rc → `npx` 找不到 → 日志:

```text
/usr/bin/env: 'node': No such file or directory
```

issue 报告者手动 workaround:systemd unit 显式写绝对 node 路径 + `Environment=PATH=...` 后 Gateway 正常启动。

Fix

```bash
NODE_BIN="$(command -v node || true)"
if [ -z "$NODE_BIN" ]; then
echo "[ERROR] 'node' not found in PATH; cannot generate Gateway start command." >&2
echo "[ERROR] If you installed Node via nvm/asdf, source the loader script for the install user before re-running:" >&2
echo "[ERROR] source ~/.bashrc # or 'nvm use '" >&2
exit 1
fi
echo "[memory-tencentdb] Resolved node: $NODE_BIN"

GATEWAY_CMD="sh -c 'cd $TDAI_INSTALL_DIR && exec \"$NODE_BIN\" --import tsx/esm src/gateway/server.ts'"
```

两点变化:

  1. 绝对路径:`command -v node` 在 install 时(user shell 已加载 nvm)resolve 出 `/root/.nvm/versions/node/v25.8.2/bin/node` 之类的绝对路径,写入 `MEMORY_TENCENTDB_GATEWAY_CMD`。systemd 直接 exec 该绝对路径,跳过 PATH 查找。
  2. 去掉 npx:用 Node 原生 `--import tsx/esm` loader 直接加载 tsx 作为 ESM register hook,跳过 `npx tsx` 这层间接(npx 自身也是个 node script,需要解析)。`--import` 在 Node ≥ 20.6 stable;脚本顶部已经声明 `Node.js >= 22` 前置条件,引入零新要求。

Install 时 `node` 不在 PATH 直接 fail-fast + 给出 nvm/asdf 用户的 hint,比生成一个不能跑的 `GATEWAY_CMD` 再等 runtime 报错好得多。

Compatibility | 兼容性

场景 之前 修复后
交互 shell(nvm `~/.bashrc` 已加载) ✅ npx 跑通 ✅ 直接 exec node 跑通
系统包管理 node(`/usr/bin/node`) ✅ npx 跑通 ✅ 绝对路径 `/usr/bin/node` 跑通
systemd service + nvm node ❌ npx 找不到(issue #19 ✅ 绝对路径不依赖 PATH
Hermes `hermes` 命令(与 systemd 等价 spawn 模式) ❌ 同上

Manual test plan

```bash

Before fix (重现 issue):

1. nvm install node 22 + hermes 装好

2. 跑 install_hermes_memory_tencentdb.sh

3. cat /etc/profile.d/memory-tencentdb-env.sh → 看到裸 npx

4. 用 systemd unit 启动 → 日志 'node: No such file or directory'

After fix:

1. 同上 1-2 步

3. cat /etc/profile.d/memory-tencentdb-env.sh → 看到绝对 node 路径

export MEMORY_TENCENTDB_GATEWAY_CMD="sh -c 'cd ... && exec \"/root/.nvm/.../node\" --import tsx/esm src/gateway/server.ts'"

4. 用 systemd unit 启动 → curl http://127.0.0.1:8420/health 返回 200

```

Edge cases handled

  • node 不在 install 用户的 PATH:fail-fast,明确报错 + nvm/asdf hint,不生成损坏的 GATEWAY_CMD。
  • node 路径含空格:`\"$NODE_BIN\"` 在 `sh -c` 内部用双引号保护,spaces in path 不会破坏 GATEWAY_CMD 语义(虽然 nvm/系统路径通常不含空格,但作为防御性 quoting)。

Out of scope

  • 不动 `memory-tencentdb-ctl.sh` 或 `hermes-plugin/memory/memory_tencentdb/init.py` 中的 `_discover_gateway_cmd()` —— 那是 fallback 路径,被 `MEMORY_TENCENTDB_GATEWAY_CMD` 优先级覆盖。如果腾讯团队希望 fallback 也走 absolute path,可以单独 follow-up。
  • 不为 shell script 引入测试基础设施(项目暂无 bats / shellcheck CI);手动验证步骤见上。

DCO

Commit 带 `Signed-off-by: 李冠辰 liguanchen@xiaomi.com`。

Closes #19.

When Hermes (or a standalone memory-tencentdb-gateway service) runs under
systemd, the systemd environment's PATH is the minimal default
(``/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin``) and
does NOT inherit the user shell's nvm/asdf-augmented PATH. nvm installs
node under ``~/.nvm/versions/node/v*/bin/`` and systemd cannot find it.

Reported in Tencent#19 by @cuiweiyou: the install script's generated launch
command used a bare ``npx tsx ...``. In an interactive shell (with nvm
loaded via ``~/.bashrc``) this ran fine, but under systemd the fork-exec
failed with ``/usr/bin/env: 'node': No such file or directory``, and the
Gateway never came up. Hermes' watchdog kept logging "Gateway
unreachable; attempting to resurrect."

Fix: resolve ``node`` to its absolute path at install time via
``command -v node``, and use Node's native ``--import tsx/esm`` loader
instead of ``npx`` so the final command has no runtime PATH dependency.

  Before:
    sh -c 'cd <plugin-dir> && exec npx tsx src/gateway/server.ts'

  After (NODE_BIN resolved at install time, e.g.
  /root/.nvm/versions/node/v25.8.2/bin/node):
    sh -c 'cd <plugin-dir> && exec "<NODE_BIN>" --import tsx/esm src/gateway/server.ts'

A guard fails the install with a clear error message if ``node`` is not
on PATH at install time, with hints for nvm/asdf users to source their
loader script first.

``--import tsx/esm`` is stable in Node ≥ 20.6 (and the script already
requires Node ≥ 22, see header comment), so this introduces no new
runtime requirement.

Closes Tencent#19.

Signed-off-by: 李冠辰 <liguanchen@xiaomi.com>
@Maxwell-Code07
Copy link
Copy Markdown
Collaborator

Hi @YOMXXX,

We've received your PR regarding the node path resolution in systemd environments. Thanks for the contribution! We'll review and follow up.

@noFloat
Copy link
Copy Markdown
Collaborator

noFloat commented May 21, 2026

内部已修改,随下个版本发出

@noFloat noFloat closed this May 21, 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.

Hermes systemd 场景下 MEMORY_TENCENTDB_GATEWAY_CMD 使用 npx 容易找不到 node

3 participants