使用Node.JS时子进程无法被终止

19

我使用child_process.exec / child_process.spawn来派生新进程,然后使用child.kill / process.kill杀死它。这对于简单的二进制可执行文件(如cat / ls)可以正常工作,并且子进程就被杀死了。

但是,当涉及到脚本(比如P1)派生了另一个子进程(比如P2)时,只有脚本解释器P1被杀死,而不是子进程P2。

问题:有没有办法在Node.JS中使这样的子进程P2被终止?

代码对于run_and_kill('ls -Al /usr/lib')可以正常工作,但对于run_and_kill('firefox')则不行:

function run_and_kill(cmd) {
    var exec = require('child_process').exec,
        ls = exec(cmd);
    console.log('Child process started: %d', ls.pid);
    ls.on('exit', function(code, signal) {
        console.log('exit with code %s and signal %s', code, signal);
    });
    ls.kill();
}

你可以尝试手动杀死它们(可能P2会忽略SIGHUP)- https://dev59.com/UHRC5IYBdhLWcg3wKtv2 - Andrey Sidorov
@AndreySidorov 如何在不知道其PID的情况下手动终止进程? - Ghostoy
你知道它 - ls.pid(https://github.com/joyent/node/blob/master/lib/child_process.js#L250) - Andrey Sidorov
@AndreySidorov 我的意思是 P2 的 PID,因为杀死 P1 并不会使 P2 退出。 - Ghostoy
你的P2 Node.js脚本中能够处理SIGHUP信号吗? - Andrey Sidorov
显示剩余3条评论
3个回答

4
我找到的最安全的方法是创建一个生成进程来杀死信号,使用 child.pid 作为参数。以下是使用 fork 的示例:
var process;
process = require('child_process');

var fork, child;
fork = process.fork;
child = fork('./index');

var spawn;
spawn = process.spawn;
spawn('kill', [child.pid]);
console.log('sending SIGTERM to child process (socket server)');

我通常在规范中使用它,主要在beforeAll/afterAll块中启动/关闭服务器(在示例中为'./index.js')。


只要那些子进程也退出,这就可以工作了 :) 他们应该会退出。 - Alexander Mills

2
在我的情况下,问题是进程使用的shell。默认情况下是/bin/sh,当使用它时,它无法处理kill信号。
要解决这个问题,您可以改用/bin/bash
exec('your command', {
    shell: '/bin/bash',
});

你有没有想过在Windows系统上有什么等效的解决方案? - Sheldonfrith

1

我认为你的P2既不是P1的分支也不是子进程,而是由它生成的并行进程。在Firefox(至少在Linux中)的情况下,firefox应用程序是由包装器shell脚本启动的。如果它总是要运行Firefox,最好直接从其安装文件夹运行二进制文件。


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