多个 node 服务在 vscode 中卡在 eaddrinuse 是因 v8 调试端口 9229 被复用,前一个调试会话未彻底退出导致内核残留监听套接字;解决方法是避免 launch.json 硬编码 port: 9229,改用 9230+ 不重叠端口区间,并同步更新 nodemon、ts-node 或子进程的 --inspect-brk 参数,确保端口唯一且显式指定。

为什么多个 Node 服务在 VSCode 里总卡在 EADDRINUSE?
不是你代码写错了,而是 V8 调试端口(默认 9229)被复用。VSCode 启动调试时会为每个 launch.json 配置尝试监听同一端口,一旦前一个调试会话没彻底退出(比如 Ctrl+C 中断、窗口直接关闭),套接字就留在 TIME_WAIT 状态,新会话立刻报 Error: listen EADDRINUSE: address already in use :::9229。
常见错误现象:
- 第二个调试会话启动失败,控制台只显示“正在启动调试器…”然后静默退出
- VSCode 左下角状态栏出现红色感叹号,但没具体错误提示
- 手动
lsof -i :9229查不到进程,却仍无法绑定——说明是内核残留 socket,不是用户态进程占着
怎么让多个 Node 服务在 VSCode 里各自用独立调试端口?
核心是避免硬编码 port: 9229,改用可变且不重叠的端口区间,并确保所有相关配置对齐。
使用一条命令部署ProbeChain Rydberg测试网代理节点。自动注册为Agent(NodeType=1),免gas,支持macOS/Linux/Windows。触发词:/r
- 在
.vscode/launch.json中,把每个配置的"port"改成不同值,推荐从9230开始递增,比如9230、9231、9232 - 如果用了
nodemon或ts-node,必须同步改runtimeArgs里的--inspect-brk参数,例如:["--inspect-brk=9231", "${workspaceFolder}/src/app2.js"] - Worker Threads 或
child_process.fork()子进程,要在创建时传execArgv: ['--inspect-brk=9232'],且和父进程launch.json的port一致 - 不要用
0作为端口号(如--inspect-brk=0)——VSCode 的autoAttachChildProcesses不识别自动分配端口,必须显式指定
autoAttachChildProcesses 为什么开了还是连不上子进程?
这个选项只起开关作用,但依赖三个前提同时满足:端口唯一、参数透传、启动路径正确。缺一不可。
-
"autoAttachChildProcesses": true必须写在主进程的launch.json配置顶层,不是嵌套在configurations外 - 子进程必须由
child_process.fork()或new Worker()创建;spawn()默认不带调试参数,需手动加execArgv - 主进程和子进程不能共用同一调试端口——Node.js 不允许多个监听器 bind 同一地址+端口,哪怕 IP 不同也不行
- 若项目用
ts-node启动主进程,autoAttachChildProcesses会失效,因为ts-node是 wrapper 进程,不是原生 Node 启动流程
调试端口冲突后,怎么快速清理“幽灵残留”?
杀进程只是表象,真正要清的是内核未释放的 socket。别反复重启 VSCode,先做这几步:
- macOS/Linux:运行
lsof -i :9230(替换成你实际用的端口),若无输出但依然报错,执行sudo lsof -i -P -n | grep LISTEN找出所有node相关监听项,再kill -9 PID - Windows:PowerShell 中运行
Get-NetTCPConnection -LocalPort 9230 | Select-Object OwningProcess,State,拿到OwningProcess后用tasklist /fi "pid eq <code>PID"确认是不是node.exe,再taskkill /f /pid <code>PID - 临时预防:在
launch.json的preLaunchTask里加个端口检查脚本,或干脆改用--inspect-port=0让 Node 自选空闲端口(但 VSCode 不支持自动读取该端口,慎用)
最易被忽略的一点:VSCode 的调试器不会主动回收已断开的调试连接,尤其当你在调试中途关掉终端或强制退出,那个端口监听器就“活着但没人管”。每次换端口前,最好先确认旧端口是否真空闲,而不是凭经验跳过检查。










