Le dernier bit du code, ;:
exécute la fonction :(){ ... }
. C'est là que la fourche se produit.
Le point-virgule termine la première commande, et nous en commençons une autre, c'est-à-dire en invoquant la fonction :
. La définition de cette fonction inclut un appel à lui-même ( :
) et la sortie de cet appel est dirigée vers une version en arrière-plan :
. Cela soutient indéfiniment le processus.
Chaque fois que vous appelez la fonction :()
que vous appelez la fonction C fork()
. Finalement, cela épuisera tous les ID de processus (PID) sur le système.
Exemple
Vous pouvez échanger le |:&
avec quelque chose d'autre pour vous faire une idée de ce qui se passe.
Configurer un observateur
Dans une fenêtre de terminal, procédez comme suit:
$ watch "ps -eaf|grep \"[s]leep 61\""
Configuration de la bombe à fourche "fusible retardé"
Dans une autre fenêtre, nous exécuterons une version légèrement modifiée de la bombe à fourche. Cette version tentera de se limiter afin que nous puissions étudier ce qu'elle fait. Notre version dormira pendant 61 secondes avant d'appeler la fonction :()
.
Nous allons également mettre en arrière-plan l'appel initial, après son appel. Ctrl+ z, puis tapez bg
.
$ :(){ sleep 61; : | : & };:
# control + z
[1]+ Stopped sleep 61
[2] 5845
$ bg
[1]+ sleep 61 &
Maintenant, si nous exécutons la jobs
commande dans la fenêtre initiale, nous verrons ceci:
$ jobs
[1]- Running sleep 61 &
[2]+ Running : | : &
Après quelques minutes:
$ jobs
[1]- Done sleep 61
[2]+ Done : | :
Vérifiez auprès de l'observateur
Pendant ce temps, dans l'autre fenêtre où nous courons watch
:
Every 2.0s: ps -eaf|grep "[s]leep 61" Sat Aug 31 12:48:14 2013
saml 6112 6108 0 12:47 pts/2 00:00:00 sleep 61
saml 6115 6110 0 12:47 pts/2 00:00:00 sleep 61
saml 6116 6111 0 12:47 pts/2 00:00:00 sleep 61
saml 6117 6109 0 12:47 pts/2 00:00:00 sleep 61
saml 6119 6114 0 12:47 pts/2 00:00:00 sleep 61
saml 6120 6113 0 12:47 pts/2 00:00:00 sleep 61
saml 6122 6118 0 12:47 pts/2 00:00:00 sleep 61
saml 6123 6121 0 12:47 pts/2 00:00:00 sleep 61
Hiérarchie des processus
Et un ps -auxf
montre cette hiérarchie de processus:
$ ps -auxf
saml 6245 0.0 0.0 115184 5316 pts/2 S 12:48 0:00 bash
saml 6247 0.0 0.0 100988 468 pts/2 S 12:48 0:00 \_ sleep 61
....
....
saml 6250 0.0 0.0 115184 5328 pts/2 S 12:48 0:00 bash
saml 6268 0.0 0.0 100988 468 pts/2 S 12:48 0:00 \_ sleep 61
saml 6251 0.0 0.0 115184 5320 pts/2 S 12:48 0:00 bash
saml 6272 0.0 0.0 100988 468 pts/2 S 12:48 0:00 \_ sleep 61
saml 6252 0.0 0.0 115184 5324 pts/2 S 12:48 0:00 bash
saml 6269 0.0 0.0 100988 464 pts/2 S 12:48 0:00 \_ sleep 61
...
...
Temps de nettoyage
A killall bash
arrêtera les choses avant qu'elles ne deviennent incontrôlables. Faire votre nettoyage de cette façon peut être un peu dur, une manière plus douce et plus douce qui ne détruira pas potentiellement chaque bash
coquille, serait de faire ce qui suit:
Déterminez dans quel pseudo terminal la bombe à fourche va s'exécuter
$ tty
/dev/pts/4
Tuez le pseudo terminal
$ pkill -t pts/4
Alors que se passe-t-il?
Eh bien, chaque appel de bash
et sleep
est un appel à la fonction C à fork()
partir du bash
shell à partir duquel la commande a été exécutée.