标签: WSL · Node.js · Linux · 后端 · 踩坑记录
01 问题
在 WSL Ubuntu 里装了 Hermes Agent,配了 Dashboard(9119)和 hermes-web-ui(8648)。两个服务都起来了,浏览器能打开,登录也正常。
但发送消息没反应。
没有报错,没有超时,就是安静地不动。
02 排查
查了一下端口情况:
| 端口 | 服务 | 状态 |
|---|---|---|
| 9119 | Hermes Dashboard | 监听中 |
| 8642 | Hermes Gateway(后端 API) | 没起来 |
| 8648 | hermes-web-ui(前端) | 监听中 |
问题找到了:8642 端口没开,Web UI 根本连不上后端 API。
03 第一次尝试:nohup + disown
先启动 Hermes Gateway:
bash
nohup hermes gateway run > hermes_gateway.log 2>&1 &
disown
8642 端口起来了。关闭终端再检查------端口没了。
原因:用 subprocess.run() 调 WSL 命令,每次都是一个新的 bash 进程。进程结束后,它衍生的所有子进程也会一起被清理。
04 第二次尝试:hermes-web-ui 也用 nohup
bash
nohup /usr/bin/node /usr/lib/node_modules/hermes-web-ui/dist/server/index.js > webui.log 2>&1 &
disown
进程秒退。日志到 gateway manager initialized 就停了,没有报错。
Python 进程用 nohup 还能撑一会儿,Node.js 进程直接退出了。disown 对 Node.js 不起作用。
05 第三次尝试:setsid
bash
setsid /usr/bin/node /usr/lib/node_modules/hermes-web-ui/dist/server/index.js > webui.log 2>&1 < /dev/null &
还是秒退。nohup + setsid 组合也试了,一样。
06 第四次尝试:timeout
用 timeout 跑前台看看:
bash
timeout 5 /usr/bin/node /usr/lib/node_modules/hermes-web-ui/dist/server/index.js
日志完整输出:
csharp
[bootstrap] listening on 0.0.0.0:8648
Server: http://localhost:8648
服务能起来,但 timeout 结束就停了,无法常驻。
07 解法:screen -dmS
换用 screen:
bash
screen -dmS hermes-webui /usr/bin/node /usr/lib/node_modules/hermes-web-ui/dist/server/index.js
8648 端口稳稳亮起,进程在 screen 会话里挂着,关闭终端也不掉。
Gateway 同样用 screen:
bash
screen -dmS hermes-gateway bash -c "source ~/.hermes/hermes-agent/.venv/bin/activate && exec hermes gateway run > hermes_gateway.log 2>&1"
08 为什么 nohup 对 Node.js 无效
nohup 负责忽略 SIGHUP 信号,这部分没问题。真正的问题在于父进程生命周期。
- Python 进程被 nohup 后,父 bash 退出时会被 init 接管,继续运行
- Node.js 对 SIGHUP 的处理有时会触发额外清理逻辑,或者 V8 垃圾回收在没有 TTY 时行为异常,导致进程主动退出
screen 创建了一个真正的守护终端,Node.js 运行在一个完整会话里,不依赖任何父进程。
结论
WSL/Linux 里让 Node.js 服务持久运行的正确方式:
bash
# ✅ screen
screen -dmS <session-name> node your-app.js
# ❌ nohup / disown / setsid 对 Node.js 均不可靠
把持久化交给 screen。