Je pourrais être rétrogradé pour cela, mais je ne comprends pas où je me trompe.
J'essaie de générer un processus en javascript et de le tuer après un certain temps (pour le test).
En fin de compte, le processus sera une boucle infinie que je dois redémarrer avec différents arguments à une heure précise. Je pensais donc que créer et tuer le processus était la meilleure façon de le faire.
Mon code de test est:
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);
});
Le résultat est:
#~$ node test.js
Timeout
kill
Mais je dois encore envoyer ctrl + C pour terminer le programme
Qu'est-ce que je rate?
EDIT: Sur Raspbian, noeud 0.10.17, omxplayer est un binaire (lecteur vidéo).
Essayé: Ajouté chmod + x à l'application . Lancé en tant que root . Stdin en pause du processus enfant. Utilisation de tous les signaux liés à la terminaison dans la commande kill.
EDIT2:
Lancement d'une commande ps pendant l'exécution de l'application:
2145 bash
2174 node
2175 omxplayer
2176 omxplayer.bin
2177 ps
Donc, omxplayer est un wrapper qui ne termine pas le processus à la fin. Y at-il un moyen d’obtenir le pid du processus emballé?
EDIT3:
Toujours mordant la poussière, a essayé ceci:
spawn('kill', ['-QUIT', '-$(ps opgid= '+child.pid+')']);
Ce qui, à mon avis, tuerait tous les enfants d’OMXplayer, je ne sais pas si utiliser spawn de la sorte est faux ou si c’est le code qui ne fonctionne pas.
Dernière édition:
La dernière modification que j'ai faite était la bonne réponse, mais a du être trompée un peu.
J'ai créé un fichier sh (avec exécuter à droite) comme ceci:
PID=$1
PGID=$(ps opgid= "$PID")
kill -QUIT -"$PGID"
Que je commence comme ça:
execF('kill.sh', [child.pid], function(){
console.log('killed');
});
Au lieu de child.kill.
Je ne suis pas sûr que ce soit la meilleure façon de procéder, ni si le code est propre, mais cela fonctionne.
J'accepterai toute réponse qui la rende plus propre ou meilleure sans avoir à exécuter de fichier.
Reportez-vous à cette discussion
Une fois que vous avez commencé à écouter les données sur stdin, le noeud attendra l’entrée sur stdin jusqu’à ce qu’on lui dise de ne pas le faire. Lorsque l'utilisateur appuie sur ctrl-d (la fin de la saisie) ou que le programme appelle stdin.pause (), le noeud cesse d'attendre le stdin.
Un programme de nœud ne se ferme que s'il n'a rien à faire ou à attendre. Ce qui se passe, c’est qu’il attend stdin et ne quitte donc jamais.
Essayez de changer votre rappel setTimeout en
console.log('kill');
child.stdin.pause();
child.kill();
J'espère que ça devrait marcher.
Il existe un npm package appelé tree-kill
très soigné, qui le fait très facilement et efficacement. Il tue le processus enfant, et tous les processus enfants que cet enfant a pu démarrer.
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);
});
J'ai eu exactement le même problème que vous avec omxplayer et la solution de cet article de blog a fonctionné pour moi.
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);
Pourquoi n'envoyez-vous pas simplement la valeur 'q' dans le tube stdin? Cela tue le processus omxplayer.
Vous avez généré un processus enfant qui a été tué avec succès. Cependant, votre thread principal est toujours en cours d'exécution, c'est pourquoi vous devez appuyer sur Ctrl + C.
Essayez d’utiliser la méthode child_process.execFile()
à partir de ici .
La fonction child_process.execFile () est similaire à child_process.exec () sauf qu'il ne génère pas de shell. Plutôt, le fichier exécutable spécifié est créé directement en tant que nouveau processus ce qui le rend légèrement plus efficace que child_process.exec ().
Cela fonctionne dans mon cas.
Enfin, j'ai trouvé comment le faire sans script:
exec('pkill omxplayer', function(err, stdout, stderr){
if (stdout){console.log('stdout:'+stdout);}
if (stderr){console.log('stderr:'+stderr);}
if (err){throw err;}
//...
}