Ostatni bit kodu ;:
uruchamia funkcję :(){ ... }
. W tym miejscu występuje widelec.
Średnik kończy pierwsze polecenie, a my rozpoczynamy kolejne, tzn. Wywołujemy funkcję :
. Definicja tej funkcji obejmuje wywołanie do siebie ( :
), a wynik tego wywołania jest przesyłany do wersji w tle :
. To wspiera proces na czas nieokreślony.
Za każdym razem, gdy wywołanie funkcji :()
jesteś wywołanie funkcji C fork()
. Ostatecznie spowoduje to wyczerpanie wszystkich identyfikatorów procesów (PID) w systemie.
Przykład
Możesz zamienić się |:&
czymś innym, aby dowiedzieć się, co się dzieje.
Skonfiguruj obserwatora
Zrób to w jednym oknie terminala:
$ watch "ps -eaf|grep \"[s]leep 61\""
Ustaw bombę wideł „z opóźnieniem bezpiecznika”
W innym oknie uruchomimy nieco zmodyfikowaną wersję widełkowej bomby. Ta wersja spróbuje się dusić, abyśmy mogli przestudiować, co robi. Nasza wersja będzie spała przez 61 sekund przed wywołaniem funkcji :()
.
Będziemy również tworzyć tło pierwszego połączenia, po jego wywołaniu. Ctrl+ z, a następnie wpisz bg
.
$ :(){ sleep 61; : | : & };:
# control + z
[1]+ Stopped sleep 61
[2] 5845
$ bg
[1]+ sleep 61 &
Teraz, jeśli uruchomimy jobs
polecenie w oknie początkowym, zobaczymy:
$ jobs
[1]- Running sleep 61 &
[2]+ Running : | : &
Po kilku minutach:
$ jobs
[1]- Done sleep 61
[2]+ Done : | :
Zamelduj się u obserwatora
Tymczasem w drugim oknie, w którym działamy 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
Hierarchia procesów
A ps -auxf
pokazuje hierarchię procesów:
$ 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
...
...
Czas na sprzątanie
A killall bash
zatrzyma rzeczy, zanim wymkną się spod kontroli. Czyszczenie w ten sposób może być trochę ciężkie, łagodniejszy i łagodniejszy sposób, który potencjalnie nie rozbije wszystkich bash
pocisków, to:
Określ, w jakim pseudo terminalu ma trafić widelec bomba
$ tty
/dev/pts/4
Zabij pseudo terminal
$ pkill -t pts/4
Więc co się dzieje?
Cóż, każde wywołanie bash
i sleep
jest wywołaniem funkcji C fork()
z bash
powłoki, z której uruchomiono polecenie.