VS Code 不会自动更换 --inspect 端口,因 launch.json 中硬编码 "port": 9229 后即固定连接该端口;一旦被占(如残留进程、Chrome DevTools 或其他 IDE 占用),直接报 EADDRINUSE 错误而无 fallback 机制,必须手动改端口并确保 runtimeArgs 与 port 一致。

为什么 --inspect 端口卡死在 9229 不会自动换?
VS Code 的 Node.js 调试器默认用 9229,但它不会“自动漂移”——launch.json 里写死 "port": 9229 就永远只连这个端口。一旦被占,报 EADDRINUSE: address already in use :::9229,调试直接失败,不是重试,更不换端口。
常见诱因包括:上一个调试会话没断开、Chrome DevTools 正连着同一端口、WebStorm 或其他 IDE 也在监听、甚至残留的 node --inspect 进程还卡在 TIME_WAIT 状态。
- 别指望 VS Code 自动 fallback 到 9230 —— 它没这逻辑
-
nodemon --inspect-brk如果没显式指定端口,也默认走 9229,和 launch.json 冲突概率极高 - Chrome 访问
chrome://inspect时若手动连过本地 9229,可能维持长连接,导致端口无法释放
launch.json 怎么配才能让调试端口真正可变?
核心是两件事:不硬编码端口 + 保证 runtimeArgs 和 launch 配置一致。否则 nodemon 启一个端口,VS Code 去连另一个,必然失败。
正确写法示例(以 9230 为基准):
{
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch via nodemon",
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/nodemon",
"runtimeArgs": ["--inspect-brk=9230", "${workspaceFolder}/index.js"],
"port": 9230,
"restart": true,
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}
]
}
-
"port"字段必须和--inspect-brk=9230中的数字完全一致,差一位都不行 - 避免用
--inspect(无 brk),它不阻塞启动,VS Code 可能连不上第一帧 - 如果项目用 pnpm/yarn,确保
runtimeExecutable指向正确的nodemon路径,否则runtimeArgs会被忽略
Windows/macOS/Linux 查端口占用和杀进程的关键命令差异
查 PID 是第一步,但各系统返回格式、字段名、依赖工具都不同,错用就白忙。
- macOS/Linux:
lsof -ni :9229(-n跳 DNS,-i过滤网络连接),输出中第二列是 PID;若报command not found,先运行xcode-select --install - Windows PowerShell:
Get-NetTCPConnection -LocalPort 9229 | Select-Object OwningProcess, State,OwningProcess就是 PID,不用转换 - Windows CMD:
netstat -ano | findstr :9229,最后一列是 PID,但得去任务管理器“详细信息”页开启“PID”列才能比对
杀的时候更要小心:
- macOS/Linux:
kill 12345(先发 SIGTERM),等 2 秒没退出再kill -9 12345 - Windows:
taskkill /f /t /pid 12345,/t必须加,否则node.exe下挂的npm或子线程还在占端口 - VS Code 自身残留常藏在
Code Helper进程里,全局清理可用:killall -r "Code Helper|Electron"(macOS/Linux)或taskkill /f /t /im CodeHelper.exe(Windows)
端口冲突后 VS Code 不重连?因为旧调试会话根本没断
你点“停止”调试,只是终止了当前 session,但底层 V8 inspect server 可能还在跑——尤其当你用终端手动启过 node --inspect=9229 index.js,又没 Ctrl+C,或者调试中断异常退出,套接字就卡在 TIME_WAIT 状态。
- 每次改完
launch.json或杀完进程,务必关掉所有已打开的调试会话(顶部调试栏 × 掉全部) - 检查 Chrome:
chrome://inspect页面里删掉所有 localhost:9229 的 target,否则它会持续尝试重连 - Node.js 服务代码里如果用了
server.listen()但没实现优雅关闭(process.on('SIGINT', () => server.close())),下次启动时旧 socket 还挂着 - VS Code Remote-SSH 或 WSL 场景下,端口转发可能缓存旧绑定,需手动执行
Remote-SSH: Kill VS Code Server on Host
真正麻烦的从来不是端口本身,而是那些没彻底断开的连接状态和进程树——它们不显眼,但会让“换端口”变成无效操作。


















