如何调试Node.JS的子进程?

41

我正在尝试调试使用以下代码创建的 Node.JS 子进程:

var child = require('child_process');
child .fork(__dirname + '/task.js');

问题在于在IntelliJ/WebStorm中运行时,父进程和子进程都在同一个端口上启动。

debugger listening on port 40893
debugger listening on port 40893

因此,它只能调试父进程。

是否有一种方法可以将IntelliJ设置为调试子进程或强制其在不同的端口上启动,以便我可以在远程调试中连接它?

6个回答

30

是的,您必须在新端口中生成进程。有一种解决集群调试问题的方法,与此类似:

使用--debug命令启动您的应用程序,然后:

var child = require('child_process');
var debug = typeof v8debug === 'object';
if (debug) {   
    //Set an unused port number.    
    process.execArgv.push('--debug=' + (40894));    
}    
child.fork(__dirname + '/task.js');

监听端口40894上的调试器


我不确定为什么,但我的process.execArgv是一个数组,我不得不修改它为process.execArgv.toString().indexOf('--debug') !== -1; 才能让它正常工作。谢谢! - MorningDew
使用Node 0.12.1版本,问题仍然存在,条件没有返回true(检查调试),但按照您建议的更改端口的方式可以解决问题。 - Oleg Belousov

22

这是node.js中已知的一个bug,最近已经修复(尽管没有反向移植到v0.10版本)。

有关更多详细信息,请参见此问题:https://github.com/joyent/node/issues/5318

有一种解决方法,即为每个工作进程修改命令行,尽管API不是用于此方式的(该解决方法可能在未来停止工作)。以下是来自Github问题的源代码:

var cluster = require('cluster');
var http = require('http');

if (cluster.isMaster) {
  var debug = process.execArgv.indexOf('--debug') !== -1;
  cluster.setupMaster({
    execArgv: process.execArgv.filter(function(s) { return s !== '--debug' })
  });
  for (var i = 0; i < 2; ++i) {
    if (debug) cluster.settings.execArgv.push('--debug=' + (5859 + i));
    cluster.fork();
    if (debug) cluster.settings.execArgv.pop();
  }
}
else {
  var server = http.createServer(function(req, res) {
    res.end('OK');
  });
  server.listen(8000);
}

1
使用child.fork()能否实现相同的功能? - Guy Korland
3
当然,只需将"--debug={port}"添加到子进程的命令行参数中即可。 - Miroslav Bajtoš
请参见此评论 - lena
我在这方面遇到了困难,因为我将child_process模块影响到一个名为process的局部变量中,隐藏了node进程全局变量,因此process.execArgv未定义。请注意,“process”是一个node全局变量! - Rémy DAVID

15

快速简单修复(在使用chrome://inspect/#devices时)

var child = require('child_process');
child.fork(__dirname + '/task.js',[],{execArgv:['--inspect-brk']});

如果不使用--inspect-brk运行您的应用程序,则主进程将不会进行调试,但分叉进程将进行调试,从而避免冲突。

要在调试主进程时避免分叉的冲突;

child.fork(__dirname + '/task.js',[],{execArgv:['--inspect=xxxx']});

其中xxxx是一些未用于调试主进程的端口,虽然我尝试过在调试器中同时连接两个端口,但没有成功,即使它报告正在监听。


这对我非常有效,当其他方法都无法解决问题时,值得称赞。 - qbert65536
1
对于其他尝试使用spawn但无法正常工作的人,我发现这对我有效:child.spawn('node',['--inspect-brk', __dirname + '/task.js']); - tnrich

4
我发现在fork函数中设置“execArgv”属性可以起作用:
const child = fork('start.js', [], {
cwd: startPath,
silent: true,
execArgv: ['--inspect=10245'] });

3
如果 "process.execArgv" 不起作用,您可以尝试以下方法:
if (debug) {
    process.argv.push('--debug=' + (40894));
}

这对我有用。


1

有一种更现代的使用Chrome DevTools调试子进程(或任何进程)的方法。

使用参数启动您的应用程序

--inspect

like below:

node --debug=9200 --inspect app/main.js

你会看到每个子进程的URL消息:
Debugger listening on port 9200.
Warning: This is an experimental feature and could change at any time.
To start debugging, open the following URL in Chrome:
    chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:9200/207f2ab6-5700-4fc5-b6d3-c49a4b34a311
Debugger listening on port 9201.
Warning: This is an experimental feature and could change at any time.
To start debugging, open the following URL in Chrome:
    chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:9201/97be3351-2ea1-4541-b744-e720188bacfa
Debugger listening on port 9202.
Warning: This is an experimental feature and could change at any time.
To start debugging, open the following URL in Chrome:
    chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:9202/8eb8384a-7167-40e9-911a-5a8b902bb8c9

如果您想调试远程进程,只需将地址127.0.0.1更改为您自己的地址即可。

1
--inspect 是现代的方式,但它与这里的问题没有太多关联——调试一个子进程。 - Liang Zhou
1
Chrome不会自动发现额外的端口。您必须手动告诉它连接它们。 - Breedly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接