子进程断点不触发是因为VSCode默认只调试主进程,子进程需显式启用--inspect并配置autoAttachChildProcesses:true,且端口不能重复、必须由主进程直接fork/spawn。

为什么子进程断点不触发
调试Node.js程序时,主进程的断点一切正常,但子进程里的断点总是静悄悄跳过,这往往不是代码逻辑的错,而是调试器压根没连上子进程。VSCode默认只attach到主进程,子进程如果没有开启--inspect参数,调试器根本不知道它的存在。所以,不是断点写错了,是调试会话根本没覆盖到它。
启用autoAttachChildProcesses必须配对生效
VSCode从1.58版本开始提供了自动附加子进程的能力,但这需要三个条件同时满足,缺一不可:
"type": "node"(别用pwa-node,老项目或CI环境下它可能回退失败,让你白忙活一场)"request": "launch"(attach模式不支持这个自动附加功能)- 在
launch.json里显式声明:"autoAttachChildProcesses": true
注意,autoAttachChildProcesses不是全局开关,它只对当前这个launch配置生效。如果你是通过npm start启动的,而package.json里没加--inspect-brk,那主进程本身都没进调试模式,子进程自然更不可能被attach上。
子进程启动时必须带 --inspect 参数
即便开了自动附加,如果子进程自己没暴露调试端口,VSCode也无从下手。不少开发者会踩这些坑:
fork('./worker.js')→ 子进程没带--inspect,断点自然失效spawn('node', ['worker.js'])→ 既缺--inspect,也没分配端口,要么冲突要么静默失败
正确的做法是这样(推荐用fork):
fork('./worker.js', [], {
execArgv: ['--inspect=0.0.0.0:9230']
});
如果用spawn,就显式传参:
spawn('node', ['--inspect=0.0.0.0:9230', 'worker.js']);
⚠️ 端口千万不能重复:主进程默认占着9229,子进程必须换一个,比如9230或9231。否则EADDRINUSE错误会让子进程直接崩溃,VSCode上什么日志都看不到,只显示“断点未命中”。
调试多个子进程时容易忽略的细节
VSCode的自动附加机制是“尽力而为”的,它的限制需要心里有数:
- 它只attach当前主进程直接fork/spawn出来的子进程,不递归attach孙进程
- 子进程必须在启动后5秒内暴露调试端口,超时就会被放弃(这个超时时间可以调,比如
"timeout": 10000) - Windows下,如果子进程用
cmd /c node ...包裹,VSCode就无法识别为Node子进程,自动附加会失效 - Node版本需≥14,
async_hooks才能稳定工作,低于这个版本可能会漏掉部分子进程
真正复杂的场景,比如worker_threads和child_process混用时,与其依赖自动附加,不如直接用--inspect-brk配合手动attach。这样更可控,而且能在子进程第一行代码就停住,排查问题效率更高。