Node.js:杀死 ChildProcess#spawn 的子进程

vta*_*ine 5 process spawn child-process node.js

考虑以下代码:

import {spawn, exec} from 'child_process';

var child = spawn('su',
    [process.env.USER, '-c', 'while (true); do sleep 0.3; echo "tick"; done'], 
    {stdio: ['ignore', 'pipe', 'pipe']}
);

child.stdout.pipe(process.stdout);
child.stderr.pipe(process.stderr);

setTimeout(() => {
    child.kill();
}, 1000);
Run Code Online (Sandbox Code Playgroud)

在这里,我试图运行运行其他一些子进程的特定脚本(在该示例su中将产生一个bash进程)并关闭它。但是,我无法让它按我的预期工作。

调用child.kill()只会杀死 的父进程,su而不是它的子进程bash

可以做些什么来使其工作 - 调用exec(`pkill -TERM -P ${child.pid}`)而不是child.kill(). 据我了解,这将杀死父进程的整个进程树child.pid

然而,当将两种方法结合在一起时,它有一些奇怪的地方:

setTimeout(() => {
    child.kill();
    exec(`pkill -TERM -P ${child.pid}`);
}, 1000);`
Run Code Online (Sandbox Code Playgroud)

tick即使在进程被终止后,此代码也会继续写入控制台。

为什么会发生这种情况?有人可以解释一下吗?

Ric*_*ong 7

我面临着确切的问题。我从如何杀死在 Node.js 中生成自己的子进程的子进程中找到了解决方案。

这是代码的工作形式:

const {spawn, exec} = require('child_process');

var child = spawn('./test.sh',
    [], 
    {stdio: ['ignore', 'pipe', 'pipe'], detached: true} // <---- this
);

child.stdout.pipe(process.stdout);
child.stderr.pipe(process.stderr);

setTimeout(() => {
    process.kill(-child.pid); // <---- and this
    // child.kill();
}, 1000);
Run Code Online (Sandbox Code Playgroud)

当我运行您的原始代码时,终端阻止我su从脚本运行,因此我将测试代码修改为./test.sh,它执行相同的操作:

(while (true); do sleep 0.3; echo "tick"; done)
Run Code Online (Sandbox Code Playgroud)

所以发挥魔力的两行代码是detached:trueprocess.kill(-child.pid)

引用自原网站

我们可以使用 {detached: true} 选项启动子进程,这样这些进程就不会附加到主进程,但它们将进入一组新的进程。然后在主进程上使用 process.kill(-pid) 方法,我们可以杀死具有相同 pid 组的子进程同一组中的所有进程。