Desova e mate um processo no nó.js

Posso estar em desvantagem por isto, mas não percebo onde estou a ir mal.

Estou a tentar criar um processo em javascript, e matá-lo depois de algum tempo (para teste).

No final, o processo será um loop infinito que eu preciso reiniciar com diferentes argumentos em tempo especificado, então eu pensei que criar o processo e matá-lo era a melhor maneira de fazer isso.

o meu código de teste é:

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

o resultado é:

#~$ node test.js
Timeout
kill
Mas ainda preciso de ... enviar ctrl+C para terminar o programa

O que me está a escapar?

editar: Em Raspbian, nó 0.10.17, omxplayer é um player binário.

Tentei.: Adicionou chmod +x à aplicação. Lançado como root. Stdin em pausa do processo infantil. Usando todos os sinais relacionados com a terminação no comando kill.

EDIT2:

lançou um comando ps enquanto a aplicação estava em execução:

2145    bash
2174    node
2175    omxplayer
2176    omxplayer.bin
2177    ps
Então o omxplayer do é um invólucro, que não termina o processo quando termina, existe alguma maneira de obter o pid de o processo encerrado?

EDIT3:

Ainda a morder o pó, tentei isto.
spawn('kill', ['-QUIT', '-$(ps opgid= '+child.pid+')']);
O que pensei que ia matar todas as crianças do omxplayer, não sei se usar spawn assim é errado ou se é o código que não funciona.

ÚLTIMA EDIÇÃO:

A última edição que fiz foi a boa resposta, mas teve de ser enganada um pouco.

criei um ficheiro sh (com Executar à direita) como este:

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

que começo assim:

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

em vez de crianca.matar.

Não sei se é a melhor maneira de fazer, nem se o código está limpo, mas funciona.

Aceitarei qualquer resposta que a torne mais limpa ou melhor, sem ter de executar um ficheiro.

Author: DrakaSAN, 2013-09-09

7 answers

Consulte esta discussão

Assim que começar a ouvir os dados do stdin, o nó irá esperar pela entrada do stdin até que lhe seja dito para não o fazer. Quando o usuário carrega ctrl-d (significando fim de entrada) ou o programa chama stdin.pausa (), o nó pára de esperar no stdin.

UM programa de nó não sai a menos que não tenha nada para fazer ou esperar. O que está a acontecer é que está à espera do stdin e, portanto, nunca sai.

Tente mudar a sua chamada de setTimeout para

console.log('kill');
child.stdin.pause();
child.kill();
Espero que funcione.
 35
Author: robinkc, 2013-09-09 09:10:47

Existe um pacote npm realmente limpo chamadotree-kill Que Faz isto muito fácil e eficazmente. Mata o processo Infantil, e Todos os processos infantis que a criança possa ter iniciado.

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);
});
 9
Author: Michael Hall, 2017-03-02 02:36:38

Tive exactamente o mesmo problema que tu com o omxplayer e a solução em Este post funcionou para mim.

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);
 8
Author: mikenolan, 2015-03-19 10:11:40
Por que não envia o valor " q " no tubo stdin ? Acaba com o processo do omxplayer.
 1
Author: Superdrac, 2015-09-08 15:10:31
Gerou um processo infantil que foi morto com sucesso. No entanto, o seu tópico principal ainda está a ser executado, razão pela qual tem de carregar em Ctrl+C.
 0
Author: apscience, 2013-09-09 08:58:23
Finalmente, descobri como fazê-lo sem script:
exec('pkill omxplayer', function(err, stdout, stderr){
    if (stdout){console.log('stdout:'+stdout);}
    if (stderr){console.log('stderr:'+stderr);}
    if (err){throw err;}
    //...
}
 0
Author: DrakaSAN, 2015-07-29 05:06:03

Tente usar o método child_process.execFile() a partir de aqui .

O processo infantil.a função executfile () é semelhante à processo infantil.exec () excepto que não cria uma concha. Bastante, o ficheiro executável indicado é gerado directamente como um novo processo tornando-o um pouco mais eficiente do que o child_process.execucao().

No meu caso, funciona.
 0
Author: Stinger112, 2016-02-09 19:53:13