在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()稍有效率。
它适用于我的情况。