请考虑以下代码:
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);
在这里,我正在尝试运行特定的脚本,该脚本运行其他子进程(在该示例中su
将生成bash
进程)并将其全部关闭。但是,我无法让它按预期工作。
调用child.kill()
会导致su
的父进程而不是其子bash
。
可以采取哪些措施使其有效 - 调用exec(`pkill -TERM -P ${child.pid}`)
代替child.kill()
。据我了解,这将使用父child.pid
杀死整个进动树。
然而,将两种方法结合在一起时有一些奇怪之处:</ p>
setTimeout(() => {
child.kill();
exec(`pkill -TERM -P ${child.pid}`);
}, 1000);`
即使在进程被终止后,此代码仍继续将tick
写入控制台。
为什么会这样?有人可以解释一下吗?
答案 0 :(得分:1)
我遇到了确切的问题。我从How to kill child processes that spawn their own child processes in 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);
当我运行原始代码时,终端阻止我从脚本运行su
,因此我将测试代码修改为./test.sh
,这也是同样的事情:
(while (true); do sleep 0.3; echo "tick"; done)
执行魔术的行是detached:true
和process.kill(-child.pid)
。
我们可以使用{detached:true}选项启动子进程,这样这些进程就不会附加到主进程,但会进入一组新的进程。然后在主进程上使用process.kill(-pid)方法,我们可以使用相同的pid组杀死同一组子进程中的所有进程。