Ich versuche, einen Prozess in Javascript zu erzeugen und ihn nach einiger Zeit zu beenden (zu Testzwecken).
Am Ende wird der Prozess eine Endlosschleife sein, die ich zu einem bestimmten Zeitpunkt mit verschiedenen Argumenten neu starten muss. Daher dachte ich, dass das Abrufen und Beenden des Prozesses der beste Weg ist, dies zu tun.
Mein Testcode lautet:
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);
});
Das Ergebnis ist:
#~$ node test.js
Timeout
kill
Aber ich muss immer noch Strg + C senden, um das Programm zu beenden. Was vermisse ich?
Auf Raspbian, Knoten 0.10.17, ist Omxplayer eine Binärdatei (Video-Player).
Ich habe es versucht:
chmod +x
Zur App hinzugefügt .- Als root gestartet.
- Pause des untergeordneten Prozesses. Verwenden aller terminierungsbezogenen Signale im Befehl kill.
Ich habe auch einen ps
Befehl gestartet, während die App ausgeführt wurde:
2145 bash
2174 node
2175 omxplayer
2176 omxplayer.bin
2177 ps
Omxplayer ist also ein Wrapper, der den untergeordneten Prozess nicht beendet, wenn er endet. Gibt es eine Möglichkeit, die PID des verpackten Prozesses zu ermitteln?
Immer noch beißender Staub, versuchte dies:
spawn('kill', ['-QUIT', '-$(ps opgid= '+child.pid+')']);
Was ich dachte, würde alle Kinder von Omxplayer töten, ich weiß nicht, ob die Verwendung von Spawn so falsch ist oder ob es der Code ist, der nicht funktioniert.
Die letzte Änderung, die ich vorgenommen habe, war die gute Antwort, musste aber etwas bearbeitet werden.
Ich habe eine sh-Datei (mit Ausführungsrecht) wie folgt erstellt:
PID=$1
PGID=$(ps opgid= "$PID")
kill -QUIT -"$PGID"
Was ich so anfange:
execF('kill.sh', [child.pid], function(){
console.log('killed');
});
Anstelle von child.kill
.
Ich bin mir nicht sicher, ob dies der beste Weg ist oder ob der Code sauber ist, aber es funktioniert.
Ich akzeptiere jede Antwort, die es sauberer oder noch besser macht, ohne eine Datei ausführen zu müssen.
quelle
Antworten:
Beziehen Sie sich auf diese Diskussion
Sobald Sie anfangen, auf Daten auf stdin zu warten, wartet der Knoten auf die Eingabe auf stdin, bis er angewiesen wird, dies nicht zu tun. Wenn der Benutzer entweder Strg-D (dh Ende der Eingabe) drückt oder das Programm stdin.pause () aufruft, wartet der Knoten nicht mehr auf stdin.
Ein Knotenprogramm wird nur beendet, wenn es nichts zu tun oder zu warten hat. Was passiert ist, es wartet auf stdin und wird daher nie beendet.
Versuchen Sie, Ihren setTimeout-Rückruf in zu ändern
console.log('kill'); child.stdin.pause(); child.kill();
Ich hoffe das sollte funktionieren.
quelle
Es gibt ein wirklich nettes npm-Paket,
tree-kill
das dies sehr einfach und effektiv macht. Es beendet den untergeordneten Prozess und alle untergeordneten Prozesse, die das Kind möglicherweise gestartet hat.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); });
quelle
child.kill()
funktioniert, aber nicht. Mit NodeJS v14.15.1, Windows 10Ich hatte genau das gleiche Problem wie Sie mit Omxplayer und die Lösung in diesem Blog-Beitrag hat für mich funktioniert.
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);
quelle
Warum senden Sie nicht einfach den Wert 'q' in die stdin-Pipe? Es beendet den Omxplayer-Prozess.
quelle
Sie haben einen untergeordneten Prozess erzeugt, der erfolgreich beendet wurde. Ihr Hauptthread wird jedoch noch ausgeführt, weshalb Sie Strg + C drücken müssen.
quelle
Schließlich fand ich heraus, wie man es ohne Skript macht:
exec('pkill omxplayer', function(err, stdout, stderr){ if (stdout){console.log('stdout:'+stdout);} if (stderr){console.log('stderr:'+stderr);} if (err){throw err;} //... }
quelle
Versuchen Sie, die
child_process.execFile()
Methode von hier aus zu verwenden .In meinem Fall funktioniert es.
quelle
Sie müssen das Signal angeben:
child.kill('SIGKILL')
https://nodejs.org/api/child_process.html#child_process_subprocess_kill_signal
quelle