我正在尝试在javascript中生成一个进程,并在一段时间后将其终止(出于测试目的)。
最后,进程将是一个无限循环,我需要在指定时间使用不同的参数重新启动,所以我认为产生进程并终止它是最好的方法。
我的测试代码是:
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);
});
结果是:
#~$ node test.js
Timeout
kill
但是我仍然需要发送ctrl + C来结束程序。我错过了什么?
在Raspbian节点0.10.17上,omxplayer是二进制(视频播放器)。
我试过了:
chmod +x
。我还在应用运行时启动了ps
命令:
2145 bash
2174 node
2175 omxplayer
2176 omxplayer.bin
2177 ps
所以omxplayer是一个包装器,当它结束时不会杀死它的子进程,有没有办法得到包装进程的pid?
仍然咬着灰尘,试了一下:
spawn('kill', ['-QUIT', '-$(ps opgid= '+child.pid+')']);
我认为会杀死omxplayer的所有孩子,我不知道使用这样的spawn是错误的还是代码不起作用。
我做的最后一次编辑是一个很好的答案,但不得不进行一些编辑。
我创建了一个sh文件(执行权限),如下所示:
PID=$1
PGID=$(ps opgid= "$PID")
kill -QUIT -"$PGID"
我从这样开始:
execF('kill.sh', [child.pid], function(){
console.log('killed');
});
而不是child.kill
。
我不确定这是不是最好的方法,也不确定代码是否干净,但确实有效。
我会接受任何以更清洁的方式提供的答案,或者甚至更好,无需执行文件。
答案 0 :(得分:41)
一旦开始在stdin上监听数据,节点将等待stdin上的输入,直到被告知不要。当用户按下ctrl-d(表示输入结束)或程序调用stdin.pause()时,节点将停止等待stdin。
除非没有任何操作或等待,否则节点程序不会退出。发生的事情是,它正在等待stdin,因此永远不会退出。
尝试将setTimeout回调更改为
console.log('kill');
child.stdin.pause();
child.kill();
我希望这应该有用。
答案 1 :(得分:18)
有一个非常简洁的npm package,名为t
,可以非常轻松有效地完成这项任务。它会杀死子进程,和子进程可能已经启动的所有子进程。
tree-kill
答案 2 :(得分:8)
我与omxplayer的问题完全相同,this blog post中的解决方案对我有用。
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);
答案 3 :(得分:2)
为什么不发送' q' stdin管道中的值?它会杀死omxplayer进程。
答案 4 :(得分:0)
您已经催生了一个成功杀死的子进程。但是,您的主线程仍在执行,这就是您必须按Ctrl + C。
的原因答案 5 :(得分:0)
最后,我找到了没有脚本的方法:
exec('pkill omxplayer', function(err, stdout, stderr){
if (stdout){console.log('stdout:'+stdout);}
if (stderr){console.log('stderr:'+stderr);}
if (err){throw err;}
//...
}
答案 6 :(得分:0)
尝试使用here中的child_process.execFile()
方法。
child_process.execFile()函数类似于 child_process.exec()除了它不生成shell。相反, 指定的可执行文件直接作为新进程生成 使它比child_process.exec()稍微高效。
它适用于我的情况。
答案 7 :(得分:0)
您必须指定信号:
child.kill('SIGKILL')
https://nodejs.org/api/child_process.html#child_process_subprocess_kill_signal