[LINUX] Node.js: So töten Sie Nachkommen eines Prozesses, der von child_process.fork () gestartet wurde

In diesem Artikel wird in Node.js erläutert, wie untergeordnete Prozesse, daraus abgeleitete Enkelprozesse und daraus abgeleitete Urenkelprozesse auf einmal beendet werden.

Das Töten eines untergeordneten Prozesses beendet den Enkelprozess nicht

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?

  1. oya.js startet den ko.js-Prozess.
  2. ko.js startet den mago.js-Prozess.
  3. Nehmen wir zu diesem Zeitpunkt an, dass oya.js den Prozess von ko.js.
  4. ko.js ist geschlossen.
  5. mago.js überlebt. (* Zu diesem Zeitpunkt wird mago.js vom Init-Prozess übernommen und die übergeordnete PID wird zu 1.)

Eine solche Situation wird eintreten.

Beispielcode mit restlichem Enkelprozess

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 man einen gespawnten Prozess beendet

Wie kann ich dann den Enkelprozess beenden, wenn der gestartete untergeordnete Prozess "kill ()" lautet? Das möchte ich hier erklären.

Prozessgruppe = "Haushalt"

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.

Wie man den ganzen Prozess "Haushalt" tötet

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)

freistehend = einen anderen Haushalt schaffen

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

Abgeschlossene Form von oya.js, die Nachkommen des Prozesses tötet

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

Node.js: So töten Sie Nachkommen eines Prozesses, der von child_process.fork () gestartet wurde
Ich habe versucht, das Entwicklungsstartverfahren von Django kurz zusammenzufassen
So zeigen Sie eine Liste der mit pyenv installierbaren Versionen an
Wie fange ich mit Scrapy an?
Erste Schritte mit Python
Wie fange ich mit Django an?
Wie man einen bestimmten Prozess am Anfang und Ende der Spinne mit Scrapy einfügt
So fügen Sie ein Paket mit PyCharm hinzu
[EC2] So machen Sie mit Selen eine Bildschirmaufnahme Ihres Smartphones
[Einführung in Python] So sortieren Sie den Inhalt einer Liste effizient mit Listensortierung
Wie man lernt, bis ein Anfänger in Statistik mit der Bayes'schen Statistik beginnt
Zusammenfassung zum Erstellen einer LAMP + Wordpress-Umgebung mit Sakura VPS
So berechnen Sie die Volatilität einer Marke
Lesen einer CSV-Datei mit Python 2/3
So senden Sie eine Nachricht mit Curl an LINE
So zeichnen Sie ein 2-Achsen-Diagramm mit Pyplot
So entwickeln Sie eine Cart-App mit Django
So erstellen Sie ein Wörterbuch mit einer hierarchischen Struktur.
So legen Sie Attribute mit Mock of Python fest
Verfahren zur Erstellung plattformübergreifender Apps mit kivy
Zubu Amateur will Python starten
[Python] So löschen Sie einfach einen untergeordneten Prozess, der durch Multiprozess gestartet wurde, von einem anderen Prozess
So erhalten Sie mit Python eine Liste der Dateien im selben Verzeichnis
[Einführung in Python] So erhalten Sie den Datenindex mit der for-Anweisung
Eine neue Form der App, die mit GitHub funktioniert: So erstellen Sie GitHub-Apps
So verarbeiten Sie Kamerabilder mit Teams und Zoom
So konvertieren / wiederherstellen Sie einen String mit [] in Python
Hinweise zur Verwendung von AIST Spacon ABCI
[Python] Wie zeichnet man mit Matplotlib ein Liniendiagramm?
So erstellen Sie ein Untermenü mit dem Plug-In [Blender]
Wie identifiziere ich das Element mit der geringsten Anzahl von Zeichen in einer Python-Liste?
So erhalten Sie einen angemeldeten Benutzer mit Djangos forms.py
So konvertieren Sie ein Klassenobjekt mit SQLAlchemy in ein Wörterbuch
Wie man ein Schießspiel mit toio macht (Teil 1)
So schreiben Sie einen Listen- / Wörterbuchtyp von Python3
Erste Schritte mit Visual Studio Online ~ Das Ende der Ära der Umgebungskonstruktion ~
So geben Sie die CSV eines mehrzeiligen Headers mit Pandas aus
Ableiten der MAP-Schätzung von HMM mit PyStruct
Grundlagen von PyTorch (2) - Wie erstelle ich ein neuronales Netzwerk?
Ableiten der MAP-Schätzung von HMM mit OpenGM
Ein Memo darüber, wie man das schwierige Problem der Erfassung von FX mit AI überwinden kann
[Python] So erstellen Sie mit Matplotlib ein zweidimensionales Histogramm
Wie man strukturiertes SVM von ChainCRF mit PyStruct lernt
[Python] Wie zeichnet man mit Matplotlib ein Streudiagramm?
Zusammenfassung, wie der Status mit mehreren Funktionen geteilt wird
Führen Sie das Programm aus, ohne eine Python-Umgebung zu erstellen! !! (Erste Schritte mit Google Colaboratory)
So verarbeiten Sie Kamerabilder mit Teams und Zoom Verarbeitungsvolumen im Animationsstil
Wie man zeichnet, indem man die Farbe des Diagramms kontinuierlich mit matplotlib ändert und einfach viele Legenden anordnet
So stellen Sie eine mit Flask erstellte Web-App für Heroku bereit
So erstellen Sie mit Flask einen BOT für Cisco Webex-Teams
[Ubuntu] So löschen Sie den gesamten Inhalt des Verzeichnisses
So setzen Sie einen Hyperlink zu "file: // hogehoge" mit sphinx-> pdf
So installieren Sie NPI + Senden Sie eine Nachricht an Python
[Python] So erstellen Sie eine Liste von Zeichenfolgen Zeichen für Zeichen
So konvertieren Sie mit Python [Anwendung] von einem Array in ein Wörterbuch
So geben Sie ein Dokument im PDF-Format mit Sphinx aus
Eine Sammlung wettbewerbsfähiger Pro-Techniken, die mit Python gelöst werden können