eaddrinuse 错误表明端口9229被占用,需用lsof(macos/linux)或get-nettcpconnection(windows)查pid,再tasklist确认进程;避免launch.json硬编码端口,改用9230+区间,并确保--inspect与address配置一致。

端口被占时 EADDRINUSE 错误怎么快速定位
报错 Error: listen EADDRINUSE: address already in use :::9229,说明 V8 调试器端口 9229 已被占用——但不一定是你当前项目在用。Node.js 的 --inspect 启动后,即使进程看似退出,残留的调试监听套接字可能还在 TIME_WAIT 状态,VS Code 的调试会话也可能没彻底断开。
先别急着杀进程,分两步查:
- macOS/Linux 执行:
lsof -i :9229;若提示 command not found,先运行xcode-select --install - Windows 执行:
Get-NetTCPConnection -LocalPort 9229 | Select-Object -Property LocalAddress,State,AppliedSetting,OwningProcess(PowerShell),再用tasklist /fi "pid eq <code>PID" 确认进程名 - 注意:多个
node.exe很常见,靠 PID 判定,别只看任务管理器里“名称”列
launch.json 里硬写 port: 9229 是最大隐患
VS Code 默认用 9229,但很多项目、脚手架、甚至其他 IDE(如 WebStorm)也默认用它。一旦冲突,launch.json 里写死端口就等于每天手动改配置。
正确做法是让端口可变且避开常用范围:
- 把
"port": 9229改成"port": 9230或更高(比如 9300–9400 区间),避免和 Chrome DevTools、其他调试器撞车 - 如果用
nodemon配合调试,确保runtimeArgs里的--inspect-brk指定相同端口,例如:["--inspect-brk=9230", "${workspaceFolder}/index.js"] - 远程调试时,
address字段必须和远程服务实际监听地址一致——若服务绑的是127.0.0.1,address写localhost没问题;但若服务监听0.0.0.0,则address仍应保持localhost(SSH 端口转发后,本地视角仍是 localhost)
为什么杀完进程还报错?V8 调试端口有“幽灵残留”
Node.js 进程退出时若没触发优雅关闭(Graceful Shutdown),V8 的调试监听器不会主动释放端口。尤其在 VS Code 中 Ctrl+C 中断调试、或直接关掉终端窗口,容易留下未清理的 socket。
根据 package.json 中的 engines 字段自动检测 Node.js 版本需求,未安装 nvm 时自动安装并切换至对应版本。支持 Windows、macOS、Linux。适用于 Node.js 项目开发、版本切换和环境配置。
临时缓解可用这个小技巧:
- 启动服务前加端口检查逻辑(仅开发环境):
const server = require('net').createServer();<br>server.listen(9230, () => {<br> console.log('✅ Debugger ready on port 9230');<br> server.close();<br>}).on('error', (err) => {<br> if (err.code === 'EADDRINUSE') console.error('⚠️ Port 9230 still occupied');<br>}); - 更稳妥的是在
process.on('SIGINT', ...)和'SIGTERM'中显式调用process._debugEnd()(非公开 API,慎用)或直接用process.exit(0)确保进程终结 - VS Code 调试面板右上角点“停止”按钮,比关终端更可靠;调试结束后等几秒再重新启动
远程调试时端口映射失败,常卡在 address 和绑定地址不匹配
本地能连上 9229,远程却连不上,大概率不是端口没转发,而是服务监听地址和 VS Code 配置对不上。
典型场景:
- 远程 Node.js 服务启动命令是
node --inspect=127.0.0.1:9229 index.js→ 只监听本地回环,VS Code 即使做了端口转发也无法穿透 - 正确写法是
node --inspect=0.0.0.0:9229 index.js,再配合launch.json中"address": "localhost"(因为 SSH 隧道已把远程0.0.0.0:9229映射到本地localhost:9229) - 检查远程主机防火墙是否放行该端口(
ufw allow 9229或sudo iptables -L);云服务器还要确认安全组规则
真正麻烦的不是端口数字本身,而是调试通道两端的地址语义是否对齐——localhost 在哪一端生效,0.0.0.0 绑定在哪一端,这两处稍有偏差,就会卡在连接建立前。










