Dans cet article, nous expliquerons comment terminer les processus enfants, les processus petits-enfants qui en découlent et les processus d'arrière-petits-enfants qui en dérivent tous en même temps dans Node.js.
Node.js [child_process.fork ()] est pratique car il peut démarrer des processus enfants. Dans un processus enfant, vous pouvez utiliser fork ()
pour démarrer un processus petit-enfant, et dans un processus petit-enfant, fork ()
pour créer un processus arrière-petit-enfant, et ainsi de suite. Vous pouvez le démarrer.
Le processus enfant démarré peut être arrêté avec [subprocess.kill ()]. Cependant, cela ne peut tuer que les processus enfants directs. Qu'est-ce que ça veut dire?
kill ()
le processus de ko.js.Une telle situation se produira.
Je voudrais écrire du code qui puisse reproduire le scénario ci-dessus.
Tout d'abord, la mise en œuvre de oya.js:
oya.js
console.log('oya.js: running')
//Lorsque SIGINT est accepté
process.on('SIGINT', () => {
console.log('oya.js: SIGINT')
process.exit()
})
//Quand le processus se termine
process.on('exit', () => {
console.log('oya.js: exit')
})
//Démarrer le processus enfant
const ko = require('child_process')
.fork(__dirname + '/ko.js')
//Proc2 après 3 secondes.Quitter js
setTimeout(() => {
console.log('oya.js: ko.Je termine js...')
ko.kill('SIGINT')
}, 3000)
// ko.Quand js a fini
ko.on('exit', () => {
console.log('> Ctrl-Appuyez sur C...')
})
//La magie pour que ce processus continue de fonctionner pour toujours
setInterval(() => null, 10000)
oya.js est le code qui démarre ko.js et termine ko.js après 3 secondes. Quand je kill ()
ko.js, j'essaye d'envoyer un signal SIGINT
. Les signaux Linux ne sont pas décrits en détail ici. Pensez ici au signal «SIGINT» comme indiquant simplement la fin du processus.
Ensuite, ko.js:
ko.js
console.log('ko.js: running')
//Lorsque SIGINT est accepté
process.on('SIGINT', () => {
console.log('ko.js: SIGINT')
process.exit()
})
//Quand le processus se termine
process.on('exit', () => {
console.log('ko.js: exit')
})
//Démarrer le processus des petits-enfants
require('child_process')
.fork(__dirname + '/mago.js')
//La magie pour que ce processus continue de fonctionner pour toujours
setInterval(() => null, 10000)
Enfin, mago.js:
mago.js
console.log('mago.js: running')
//Lorsque SIGINT est accepté
process.on('SIGINT', () => {
console.log('mago.js: SIGINT')
process.exit()
})
//Quand le processus se termine
process.on('exit', () => {
console.log('mago.js: exit')
})
//La magie pour que ce processus continue de fonctionner pour toujours
setInterval(() => null, 10000)
Exécutons ce code:
$ node oya.js
oya.js: running
ko.js: running
mago.js: running
oya.js: ko.Je termine js...
ko.js: SIGINT
ko.js: exit
> Ctrl-Appuyez sur C...
Après 3 secondes, vous pouvez voir que cette sortie est sortie, oya.js kill ()
ko.js, et ko.js est terminé.
D'un autre côté, mago.js n'a pas encore reçu SIGINT
, n'a pas fini et reste.
Maintenant, appuyez sur Ctrl-C pour envoyer SIGINT
à oya.js et mago.js:
...
> Ctrl-Appuyez sur C...
^Coya.js: SIGINT
mago.js: SIGINT
mago.js: exit
oya.js: exit
Ce n'est qu'à ce moment que vous saurez que mago.js se terminera.
À mon avis, ce résultat était surprenant car je ne comprenais pas que si j'envoyais SIGINT
à ko.js, SIGINT
serait également propagé vers mago.js.
Alors, comment puis-je faire terminer le processus petit-enfant lorsque le processus enfant démarré est kill ()
? Je voudrais expliquer cela ici.
Premièrement, il existe un groupe de processus comme base du processus Linux. Il s'agit d'un concept de processus de type «ménage» qui regroupe les processus des parents, des enfants et des petits-enfants. Par exemple, si vous lancez le processus de nœud oya.js dans Bash, ko.js et mago.js fork ()
à partir de là appartiennent au même groupe de processus et reçoivent le même ID de groupe.
Si vous vérifiez l'ID de groupe (GPID) avec la commande ps
, vous pouvez voir que le même ID de groupe est en fait attribué aux trois processus de nœud:
$ 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
Comme vous pouvez le voir à partir de ce résultat, le GPID est le même que l'ID de processus (PID) de oya.js. En d'autres termes, le PID du parent devient le GPID du descendant.
Dans Node.js, vous pouvez spécifier l'ID de groupe pour terminer le processus. Tout ce que vous avez à faire est de transmettre le GPID à [process.kill ()]. À ce moment, donnez un nombre négatif. Notez que passer un nombre positif ne "kill ()" que les processus individuels, pas les groupes de processus.
const groupId = 123456
process.kill(-groupId, 'SIGINT')
À propos, lorsque Ctrl-C est pressé dans le shell, le parent, l'enfant et le petit-enfant sont tous terminés car le SIGINT
envoyé par Ctrl-C est envoyé au groupe de processus, pas au processus parent. Parce que c'est. (Source requise)
Ce que je veux faire cette fois, c'est tuer ()
ko.js et mago.js tout en gardant le processus oya.js en vie. Cependant, avec kill ()
avec GPID spécifié, oya.js sera terminé. Parce que les trois ont le même GPID:
PID PPID GPID COMMAND
17553 3528 17553 node oya.js
17554 17553 17553 node ko.js
17555 17554 17553 node mago.js
Vous devez attribuer différents GPID pour ko.js et mago.js. Pour ce faire, spécifiez détaché
comme option pour fork ()
.
oya.js
//Démarrer le processus enfant
const ko = require('child_process')
.fork(__dirname + '/ko.js', [], {detached: true})
Si cela est spécifié, ko.js et mago.js seront, pour ainsi dire, des «ménages séparés» et appartiendront à des groupes de processus différents. Vous pouvez voir que le GPID est également attribué différemment de oya.js:
$ 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
Sur la base de ce qui précède, si vous modifiez oya.js afin que les processus enfants et les processus petits-enfants puissent être arrêtés en même temps, ce sera comme suit:
oya.js
console.log('oya.js: running')
//Lorsque SIGINT est accepté
process.on('SIGINT', () => {
console.log('oya.js: SIGINT')
process.exit()
})
//Quand le processus se termine
process.on('exit', () => {
console.log('oya.js: exit')
})
//Démarrer le processus enfant
const ko = require('child_process')
.fork(__dirname + '/ko.js', [], {detached: true}) //Changements importants!
//Ko après 3 secondes.Quitter js
setTimeout(() => {
console.log('oya.js: ko.Je termine js...')
process.kill(-ko.pid, 'SIGINT') //Changements importants!
}, 30000)
// ko.Quand js a fini
ko.on('exit', () => {
console.log('> Ctrl-Appuyez sur C...')
})
//La magie pour que ce processus continue de fonctionner pour toujours
setInterval(() => null, 10000)
Enfin, exécutons ce oya.js et voyons si ko.js et mago.js sont terminés ensemble:
$ node oya.js
oya.js: running
ko.js: running
mago.js: running
oya.js: ko.Je termine js...
mago.js: SIGINT
ko.js: SIGINT
mago.js: exit
ko.js: exit
> Ctrl-Appuyez sur C...
^Coya.js: SIGINT
oya.js: exit
Comme prévu, ko.js et mago.js ont reçu SIGINT
en même temps et ont terminé. Vous pouvez également voir que oya.js est actif jusqu'à ce que vous appuyiez sur Ctrl-C.
Ce qui précède explique comment tuer les descendants du processus lancé par child_process.fork ()
de Node.js.
Recommended Posts