L'ultimo bit del codice ;:sta eseguendo la funzione :(){ ... }. Questo è dove si sta verificando il fork.
Il punto e virgola termina il primo comando e ne stiamo iniziando un altro, ovvero invocando la funzione :. La definizione di questa funzione include una chiamata a se stessa ( :) e l'output di questa chiamata viene reindirizzato a una versione in background :. Questo sostiene il processo indefinitamente.
Ogni volta che si sta chiamando la funzione :()che si sta chiamando la funzione C fork(). Alla fine ciò esaurirà tutti gli ID di processo (PID) sul sistema.
Esempio
Puoi scambiarlo |:&con qualcos'altro in modo da avere un'idea di cosa sta succedendo.
Installa un osservatore
In una finestra del terminale, procedere come segue:
$ watch "ps -eaf|grep \"[s]leep 61\""
Installare la bomba a forcella "ritardato miccia"
In un'altra finestra eseguiremo una versione leggermente modificata della bomba a forcella. Questa versione tenterà di limitare se stessa in modo da poter studiare cosa sta facendo. La nostra versione dormirà per 61 secondi prima di chiamare la funzione :().
Inoltre eseguiremo anche la chiamata iniziale, dopo che è stata invocata. Ctrl+ z, quindi digitare bg.
$ :(){ sleep 61; : | : & };:
# control + z
[1]+ Stopped sleep 61
[2] 5845
$ bg
[1]+ sleep 61 &
Ora se eseguiamo il jobscomando nella finestra iniziale vedremo questo:
$ jobs
[1]- Running sleep 61 &
[2]+ Running : | : &
Dopo un paio di minuti:
$ jobs
[1]- Done sleep 61
[2]+ Done : | :
Verifica con l'osservatore
Nel frattempo nell'altra finestra dove stiamo correndo 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
Gerarchia di processo
E a ps -auxfmostra questa gerarchia di processi:
$ 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
...
...
Tempo di pulizia
A killall bashfermerà le cose prima che sfuggano di mano. Fare la tua pulizia in questo modo può essere un po 'pesante, un modo più gentile e gentile che potenzialmente non strapperà ogni bashguscio, sarebbe fare quanto segue:
Determina in quale pseudo terminale verrà lanciata la bomba
$ tty
/dev/pts/4
Uccidi lo pseudo terminale
$ pkill -t pts/4
Quindi cosa sta succedendo?
Bene, ogni invocazione di bashed sleepè una chiamata alla funzione C fork()dalla bashshell da cui è stato eseguito il comando.