在 node.js 中生成并终止进程
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18694684/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spawn and kill a process in node.js
提问by DrakaSAN
I'm trying to spawn a process in javascript, and kill it after some time (for testing purposes).
我正在尝试在 javascript 中生成一个进程,并在一段时间后终止它(用于测试目的)。
In the end, the process will be a infinite loop that I need to restart with different arguments at specified time, so I thought that spawning the process and killing it was the best way to do this.
最后,该进程将是一个无限循环,我需要在指定时间用不同的参数重新启动,所以我认为生成进程并杀死它是最好的方法。
My test code is:
我的测试代码是:
var spawn=require('child_process').spawn
, child=null;
child=spawn('omxplayer', ['test.mp4'], function(){console.log('end');}, {timeout:6000});
console.log('Timeout');
setTimeout(function(){
console.log('kill');
child.kill();
}, 1200);
child.stdout.on('data', function(data){
console.log('stdout:'+data);
});
child.stderr.on('data', function(data){
console.log('stderr:'+data);
});
child.stdin.on('data', function(data){
console.log('stdin:'+data);
});
The result is:
结果是:
#~$ node test.js
Timeout
kill
But I still need to send ctrl+C to end the program. What am I missing?
但是我仍然需要发送 ctrl+C 来结束程序。我错过了什么?
On Raspbian, node 0.10.17, omxplayer is a binary (video player).
在 Raspbian 节点 0.10.17 上,omxplayer 是一个二进制文件(视频播放器)。
I tried:
我试过:
- Added
chmod +xto the app. - Launched as root.
- Paused stdin of the child process. Using all terminate-related signal in the kill command.
- 添加
chmod +x到应用程序。 - 以 root 身份启动。
- 暂停子进程的标准输入。在 kill 命令中使用所有与终止相关的信号。
I also launched a pscommand while the app was running:
我还在ps应用程序运行时启动了一个命令:
2145 bash
2174 node
2175 omxplayer
2176 omxplayer.bin
2177 ps
So omxplayer is a wrapper, who don t kill it's child process when it end, is there any way to get the pid of the wrapped process?
所以omxplayer是一个包装器,当它结束时谁不杀死它的子进程,有没有办法获得包装进程的pid?
Still biting dust, tried this:
还在咬灰尘,试过这个:
spawn('kill', ['-QUIT', '-$(ps opgid= '+child.pid+')']);
Which I thought would kill all children of omxplayer, I don t know if using spawn like that is wrong or if it's the code that doesn't work.
我认为这会杀死 omxplayer 的所有孩子,我不知道使用这样的 spawn 是错误的还是代码不起作用。
The last edit I made was the good answer, but had to be edited a bit.
我所做的最后一次编辑是很好的答案,但必须稍微编辑一下。
I created a sh file (with execute right) like this:
我创建了一个 sh 文件(具有执行权限),如下所示:
PID=
PGID=$(ps opgid= "$PID")
kill -QUIT -"$PGID"
Which I start like this:
我是这样开始的:
execF('kill.sh', [child.pid], function(){
console.log('killed');
});
Instead of child.kill.
而不是child.kill.
I'm not sure if it s the best way to do, nor if the code is clean, but it does work.
我不确定这是否是最好的方法,也不确定代码是否干净,但它确实有效。
I'll accept any answer which make it in a cleaner way or, even better, without having to execute a file.
我会接受任何以更简洁的方式制作它的答案,或者甚至更好,而无需执行文件。
采纳答案by robinkc
Refer to this discussion
参考这个讨论
Once you start listening for data on stdin, node will wait for the input on stdin until it is told not to. When either user presses ctrl-d (meaning end of input) or the program calls stdin.pause(), node stops waiting on stdin.
一旦您开始在 stdin 上监听数据,node 将等待 stdin 上的输入,直到它被告知不要这样做。当用户按下 ctrl-d(表示输入结束)或程序调用 stdin.pause() 时,节点停止等待 stdin。
A node program does not exit unless it has nothing to do or wait for. Whats happening is, it is waiting on stdin and therefore never exits.
节点程序不会退出,除非它无事可做或等待。发生的事情是,它正在等待标准输入,因此永远不会退出。
Try changing your setTimeout callback to
尝试将您的 setTimeout 回调更改为
console.log('kill');
child.stdin.pause();
child.kill();
I hope that should work.
我希望这应该有效。
回答by Michael Hall
There is a really neat npm package called tree-killwhich does this very easily and effectively. It kills the child process, andall child processes that child may have started.
有一个非常简洁的 npm 包tree-kill,它可以非常轻松有效地完成此操作。它会杀死子进程以及该子进程可能已启动的所有子进程。
var kill = require('tree-kill');
const spawn = require('child_process').spawn;
var scriptArgs = ['myScript.sh', 'arg1', 'arg2', 'youGetThePoint'];
var child = spawn('sh', scriptArgs);
// some code to identify when you want to kill the process. Could be
// a button on the client-side??
button.on('someEvent', function(){
// where the killing happens
kill(child.pid);
});
回答by mikenolan
I've had exactly the same issue as you with omxplayer and the solution in this blog postworked for me.
我在使用 omxplayer 时遇到了与您完全相同的问题,这篇博文中的解决方案对我有用。
var psTree = require('ps-tree');
var kill = function (pid, signal, callback) {
signal = signal || 'SIGKILL';
callback = callback || function () {};
var killTree = true;
if(killTree) {
psTree(pid, function (err, children) {
[pid].concat(
children.map(function (p) {
return p.PID;
})
).forEach(function (tpid) {
try { process.kill(tpid, signal) }
catch (ex) { }
});
callback();
});
} else {
try { process.kill(pid, signal) }
catch (ex) { }
callback();
}
};
// elsewhere in code
kill(child.pid);
回答by Superdrac
Why don't you just send the 'q' value in the stdin pipe ? It kill the omxplayer process.
为什么不直接在标准输入管道中发送“q”值?它会杀死 omxplayer 进程。
回答by DrakaSAN
Finally, I found how to do it without script:
最后,我找到了没有脚本的方法:
exec('pkill omxplayer', function(err, stdout, stderr){
if (stdout){console.log('stdout:'+stdout);}
if (stderr){console.log('stderr:'+stderr);}
if (err){throw err;}
//...
}
回答by apscience
You've spawned a child process which was successfully killed. However, your main thread is still executing, which is why you have to press Ctrl+C.
您已经生成了一个已成功终止的子进程。但是,您的主线程仍在执行,这就是您必须按 Ctrl+C 的原因。
回答by Stinger112
Try to use child_process.execFile()method from here.
尝试使用这里的child_process.execFile()方法。
The child_process.execFile() function is similar to child_process.exec() except that it does not spawn a shell. Rather, the specified executable file is spawned directly as a new process making it slightly more efficient than child_process.exec().
child_process.execFile() 函数与 child_process.exec() 类似,只是它不产生 shell。相反,指定的可执行文件作为新进程直接生成,使其比 child_process.exec() 稍微高效一些。
It works in my case.
它适用于我的情况。

