在node.js中产生并杀死一个进程

我可能会为此而低估,但我不明白我要去哪里错了。

我试图在JavaScript中产生一个进程,并在一段时间后杀死它(testing)。

最后,这个过程将是一个无限循环,我需要在指定的时间重新启动不同的参数,所以我认为产生这个过程并杀死它是最好的方法。

我的testing代码是:

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是一个二进制(video播放器)。

试过:添加chmod + x的应用程序。 以root身份启动。 暂停的孩subprocess的标准input。 在kill命令中使用所有与终止相关的信号。

EDIT2:

在应用程序运行时启动了一个ps命令:

 2145 bash 2174 node 2175 omxplayer 2176 omxplayer.bin 2177 ps 

所以omxplayer做的是一个包装,它不结束过程时,有没有办法得到包装过程的PID?

EDIT3:

仍然咬着灰尘,试图这样做:

 spawn('kill', ['-QUIT', '-$(ps opgid= '+child.pid+')']); 

我认为会杀死omplayer的所有孩子,我不知道如果使用这种产卵是错误的,或者如果它是不工作的代码。

最后编辑:

我所做的最后一个编辑是一个很好的答案,但不得不被欺骗一下。

我创build了一个sh文件(执行权限)是这样的:

 PID=$1 PGID=$(ps opgid= "$PID") kill -QUIT -"$PGID" 

我是这样开始的:

 execF('kill.sh', [child.pid], function(){ console.log('killed'); }); 

而不是child.kill。

我不知道这是最好的办法,如果代码是干净的,但它确实有效。

我会接受任何答案,使其更清洁或最好,而不必执行文件。

参考这个讨论

一旦你开始监听stdin上的数据,节点将等待stdin上的input,直到被告知不会。 当任一用户按ctrl-d(意思是input结束)或程序调用stdin.pause()时,节点停止等待stdin。

节点程序不会退出,除非它没有任何事情要做或等待。 发生什么事情,它正在等待stdin,因此从不退出。

尝试改变你的setTimeoutcallback

 console.log('kill'); child.stdin.pause(); child.kill(); 

我希望应该工作。

我和omxplayer的问题完全一样, 本博客文章中的解决scheme也适用于我。

 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); 

有一个叫做tree-kill的非常简洁的npm 包 ,它可以非常简单而有效地完成。 它会杀死subprocess, 以及subprocess可能已经开始的所有subprocess。

 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); }); 

你为什么不在stdinpipe道中发送'q'值? 它杀死了omxplayer进程。

你已经产生了一个成功杀死的儿童进程。 但是,您的主线程仍在执行,这就是为什么您必须按Ctrl + C。

最后,我发现如何做到这一点没有脚本:

 exec('pkill omxplayer', function(err, stdout, stderr){ if (stdout){console.log('stdout:'+stdout);} if (stderr){console.log('stderr:'+stderr);} if (err){throw err;} //... } 

尝试从这里使用child_process.execFile()方法。

child_process.execFile()函数与child_process.exec()类似,不同之处在于它不产生shell。 而是将指定的可执行文件直接作为一个新进程产生,使其比child_process.exec()稍有效率。

它适用于我的情况。