在node.js中生成并终止进程

Dra*_*SAN 51 javascript node.js

我可能会因此而被投票,但我不明白我哪里出错了.

我试图在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);
});
Run Code Online (Sandbox Code Playgroud)

结果是:

#~$ node test.js
Timeout
kill
Run Code Online (Sandbox Code Playgroud)

但是我仍然需要发送ctrl + C来结束程序

我错过了什么?

编辑:在Raspbian,节点0.10.17,omxplayer是二进制(视频播放器).

尝试:添加chmod + x到应用程序.以root身份发布.暂停了子进程的标准输入.在kill命令中使用所有与终止相关的信号.

EDIT2:

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

2145    bash
2174    node
2175    omxplayer
2176    omxplayer.bin
2177    ps
Run Code Online (Sandbox Code Playgroud)

因此omxplayer do是一个包装器,它在结束时不会结束进程,有没有办法获得包装进程的pid?

EDIT3:

仍然咬着灰尘,试过这个:

spawn('kill', ['-QUIT', '-$(ps opgid= '+child.pid+')']);
Run Code Online (Sandbox Code Playgroud)

我认为会杀死omxplayer的所有孩子,我不知道是否使用了这样的spawn是错的,或者它是否是不起作用的代码.

最后编辑:

我做的最后一次编辑是很好的答案,但不得不被欺骗了一下.

我创建了一个sh文件(执行权限),如下所示:

PID=$1
PGID=$(ps opgid= "$PID")
kill -QUIT -"$PGID"
Run Code Online (Sandbox Code Playgroud)

我从这开始:

execF('kill.sh', [child.pid], function(){
    console.log('killed');
});
Run Code Online (Sandbox Code Playgroud)

而不是child.kill.

我不确定这是最好的方法,代码是否干净,但它确实有效.

我将接受任何以更清洁的方式或最好的方式回答,而不必执行文件.

rob*_*nkc 42

请参阅此讨论

一旦开始在stdin上监听数据,节点将等待stdin上的输入,直到它被告知不要.当用户按下ctrl-d(表示输入结束)或程序调用stdin.pause()时,节点将停止等待stdin.

除非没有任何操作或等待,否则节点程序不会退出.发生的事情是,它正在等待stdin,因此永远不会退出.

尝试将setTimeout回调更改为

console.log('kill');
child.stdin.pause();
child.kill();
Run Code Online (Sandbox Code Playgroud)

我希望这应该有效.

  • “可写”类型上不存在“属性”暂停”。ts(2339)` (3认同)
  • 尝试child.kill('SIGKILL'),看看是否有效.child.kill()发送SIGHUP,它只是告诉控制终端关闭或控制进程关闭.我的假设是SIGKILL肯定会杀了它. (2认同)

Mic*_*all 22

有一个非常简洁的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);
});
Run Code Online (Sandbox Code Playgroud)

  • 我对这一点赞不绝口——在浪费了 5 个小时之后,这是在 Windows 7 上唯一对我有用的解决方案! (2认同)

小智 8

我和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);
Run Code Online (Sandbox Code Playgroud)


Sup*_*rac 5

为什么不直接在标准输入管道中发送“q”值?它会杀死 omxplayer 进程。