In diesem Artikel wird in Node.js erläutert, wie untergeordnete Prozesse, daraus abgeleitete Enkelprozesse und daraus abgeleitete Urenkelprozesse auf einmal beendet werden.
Node.js [child_process.fork ()] ist praktisch, da es untergeordnete Prozesse starten kann. Sie können auch "fork ()" in einem untergeordneten Prozess verwenden, um einen Enkelprozess zu starten, und dann "fork ()" in einem Enkelprozess, um einen Urenkelprozess zu erstellen, und so weiter. Sie können es starten.
Der gestartete untergeordnete Prozess kann mit [subprocess.kill ()] beendet werden. Dies kann jedoch nur direkte untergeordnete Prozesse beenden. Was bedeutet das?
Eine solche Situation wird eintreten.
Ich möchte Code schreiben, der das obige Szenario reproduzieren kann.
Erstens die Implementierung von oya.js:
oya.js
console.log('oya.js: running')
//Wenn SIGINT akzeptiert wird
process.on('SIGINT', () => {
console.log('oya.js: SIGINT')
process.exit()
})
//Wenn der Prozess endet
process.on('exit', () => {
console.log('oya.js: exit')
})
//Untergeordneten Prozess starten
const ko = require('child_process')
.fork(__dirname + '/ko.js')
//Proc2 nach 3 Sekunden.Beenden Sie js
setTimeout(() => {
console.log('oya.js: ko.Ich beende js...')
ko.kill('SIGINT')
}, 3000)
// ko.Wenn js fertig ist
ko.on('exit', () => {
console.log('> Ctrl-Drücken Sie C....')
})
//Die Magie, diesen Prozess für immer am Laufen zu halten
setInterval(() => null, 10000)
oya.js ist der Code, der ko.js startet und ko.js nach 3 Sekunden beendet. Wenn ich "kill ()" ko.js "mache, versuche ich, ein" SIGINT "-Signal zu senden. Linux-Signale werden hier nicht näher erläutert. Stellen Sie sich das SIGINT-Signal hier einfach als das Ende des Prozesses vor.
Als nächstes ko.js:
ko.js
console.log('ko.js: running')
//Wenn SIGINT akzeptiert wird
process.on('SIGINT', () => {
console.log('ko.js: SIGINT')
process.exit()
})
//Wenn der Prozess endet
process.on('exit', () => {
console.log('ko.js: exit')
})
//Starten Sie den Enkelprozess
require('child_process')
.fork(__dirname + '/mago.js')
//Die Magie, diesen Prozess für immer am Laufen zu halten
setInterval(() => null, 10000)
Schließlich mago.js:
mago.js
console.log('mago.js: running')
//Wenn SIGINT akzeptiert wird
process.on('SIGINT', () => {
console.log('mago.js: SIGINT')
process.exit()
})
//Wenn der Prozess endet
process.on('exit', () => {
console.log('mago.js: exit')
})
//Die Magie, diesen Prozess für immer am Laufen zu halten
setInterval(() => null, 10000)
Lassen Sie uns diesen Code ausführen:
$ node oya.js
oya.js: running
ko.js: running
mago.js: running
oya.js: ko.Ich beende js...
ko.js: SIGINT
ko.js: exit
> Ctrl-Drücken Sie C....
Nach 3 Sekunden können Sie sehen, dass oya.js kill ()
ko.js und ko.js beendet ist.
Auf der anderen Seite hat mago.js noch kein SIGINT erhalten, ist noch nicht fertig und bleibt bestehen.
Drücken Sie nun Strg-C, um "SIGINT" an oya.js und mago.js zu senden:
...
> Ctrl-Drücken Sie C....
^Coya.js: SIGINT
mago.js: SIGINT
mago.js: exit
oya.js: exit
Nur zu diesem Zeitpunkt werden Sie wissen, dass mago.js enden wird.
Meiner Meinung nach war dieses Ergebnis überraschend, weil ich falsch verstanden habe, dass, wenn ich "SIGINT" an ko.js sende, "SIGINT" auch an mago.js weitergegeben wird.
Wie kann ich dann den Enkelprozess beenden, wenn der gestartete untergeordnete Prozess "kill ()" lautet? Das möchte ich hier erklären.
Zunächst gibt es eine Prozessgruppe als Grundlage für den Linux-Prozess. Es ist ein "haushaltsähnliches" Konzept eines Prozesses, bei dem Eltern-, Kinder- und Enkelprozesse gruppiert werden. Wenn Sie beispielsweise den Knotenprozess oya.js in Bash starten, gehören ko.js und mago.js fork ()
von dort zur selben Prozessgruppe und erhalten dieselbe Gruppen-ID.
Wenn Sie die Gruppen-ID (GPID) mit dem Befehl ps
überprüfen, können Sie feststellen, dass den drei Knotenprozessen tatsächlich dieselbe Gruppen-ID zugewiesen ist:
$ ps -xo pid,ppid,pgid,command | grep node | grep .js
PID PPID GPID COMMAND
17553 3528 17553 node oya.js
17554 17553 17553 node ko.js
17555 17554 17553 node mago.js
Wie Sie diesem Ergebnis entnehmen können, entspricht die GPID der Prozess-ID (PID) von oya.js. Mit anderen Worten, die PID des Elternteils wird zur GPID des Nachkommen.
In Node.js können Sie die Gruppen-ID angeben, um den Prozess zu beenden. Sie müssen lediglich die GPID an [process.kill ()] übergeben. Geben Sie zu diesem Zeitpunkt eine negative Zahl an. Beachten Sie, dass beim Übergeben einer positiven Zahl nur einzelne Prozesse getötet werden, keine Prozessgruppen.
const groupId = 123456
process.kill(-groupId, 'SIGINT')
Übrigens, wenn Strg-C in der Shell gedrückt wird, werden Eltern, Kind und Enkel alle beendet, weil der von Strg-C gesendete SIGINT an die Prozessgruppe und nicht an den übergeordneten Prozess gesendet wird. Denn es ist. (Quelle erforderlich)
Dieses Mal möchte ich "kill ()" ko.js und mago.js töten, während der oya.js-Prozess am Leben bleibt. Mit kill ()
mit angegebener GPID wird oya.js jedoch beendet. Weil alle drei die gleiche GPID haben:
PID PPID GPID COMMAND
17553 3528 17553 node oya.js
17554 17553 17553 node ko.js
17555 17554 17553 node mago.js
Sie müssen unterschiedliche GPIDs für ko.js und mago.js zuweisen. Geben Sie dazu als Option für "fork ()" "losgelöst" an.
oya.js
//Untergeordneten Prozess starten
const ko = require('child_process')
.fork(__dirname + '/ko.js', [], {detached: true})
Wenn dies angegeben ist, sind ko.js und mago.js sozusagen "getrennte Haushalte" und gehören verschiedenen Prozessgruppen an. Sie können sehen, dass die GPID auch anders als oya.js zugewiesen ist:
$ ps -xo pid,ppid,pgid,command | grep node | grep .js
PID PPID GPID COMMAND
21404 3528 21404 node oya.js
21405 21404 21405 node ko.js
21406 21405 21405 node mago.js
Wenn Sie oya.js so ändern, dass untergeordnete Prozesse und Enkelprozesse gleichzeitig beendet werden können, sieht dies wie folgt aus:
oya.js
console.log('oya.js: running')
//Wenn SIGINT akzeptiert wird
process.on('SIGINT', () => {
console.log('oya.js: SIGINT')
process.exit()
})
//Wenn der Prozess endet
process.on('exit', () => {
console.log('oya.js: exit')
})
//Untergeordneten Prozess starten
const ko = require('child_process')
.fork(__dirname + '/ko.js', [], {detached: true}) //Wichtige Änderungen!
//Ko nach 3 Sekunden.Beenden Sie js
setTimeout(() => {
console.log('oya.js: ko.Ich beende js...')
process.kill(-ko.pid, 'SIGINT') //Wichtige Änderungen!
}, 30000)
// ko.Wenn js fertig ist
ko.on('exit', () => {
console.log('> Ctrl-Drücken Sie C....')
})
//Die Magie, diesen Prozess für immer am Laufen zu halten
setInterval(() => null, 10000)
Lassen Sie uns abschließend diese oya.js ausführen und prüfen, ob ko.js und mago.js zusammen fertig sind:
$ node oya.js
oya.js: running
ko.js: running
mago.js: running
oya.js: ko.Ich beende js...
mago.js: SIGINT
ko.js: SIGINT
mago.js: exit
ko.js: exit
> Ctrl-Drücken Sie C....
^Coya.js: SIGINT
oya.js: exit
Wie erwartet haben ko.js und mago.js gleichzeitig "SIGINT" erhalten und sind fertig. Sie können auch sehen, dass oya.js aktiv ist, bis Sie Strg-C drücken.
Das Obige ist die Erklärung, wie die Nachkommen des Prozesses getötet werden können, der von child_process.fork ()
von Node.js gestartet wurde.
Recommended Posts