Последний бит кода, ;:это функция :(){ ... }. Это где вилка происходит.
Точка с запятой завершает первую команду, а мы запускаем другую, то есть вызываем функцию :. Определение этой функции включает в себя вызов самой себя ( :), и результат этого вызова передается в фоновую версию :. Это поддерживает процесс на неопределенный срок.
Каждый раз , когда вы вызываете функцию :()вы вызываете функцию C fork(). В конечном итоге это приведет к исчерпанию всех идентификаторов процессов (PID) в системе.
пример
Вы можете поменяться |:&с чем-то другим, чтобы вы могли понять, что происходит.
Настройте наблюдателя
В одном окне терминала сделайте это:
$ watch "ps -eaf|grep \"[s]leep 61\""
Настройте "взрыватель с задержкой" вилка бомба
В другом окне мы запустим слегка модифицированную версию вилочной бомбы. Эта версия попытается задушить себя, чтобы мы могли изучить, что она делает. Наша версия будет спать в течение 61 секунды перед вызовом функции :().
Кроме того, мы также отправим фоновый вызов после его вызова. Ctrl+ z, затем введите bg.
$ :(){ sleep 61; : | : & };:
# control + z
[1]+ Stopped sleep 61
[2] 5845
$ bg
[1]+ sleep 61 &
Теперь, если мы запустим jobsкоманду в начальном окне, мы увидим это:
$ jobs
[1]- Running sleep 61 &
[2]+ Running : | : &
Через пару минут:
$ jobs
[1]- Done sleep 61
[2]+ Done : | :
Проверьте с наблюдателем
Тем временем в другом окне, где мы бежим 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
Иерархия процессов
И ps -auxfпоказывает эту иерархию процесса:
$ 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
...
...
Время уборки
А killall bashостановит вещи прежде, чем они выйдут из-под контроля. Выполнение очистки таким образом может быть немного тяжелым, более мягким способом, который потенциально не разрушит каждую bashраковину, было бы сделать следующее:
Определите, в каком псевдо-терминале будет работать вилочная бомба
$ tty
/dev/pts/4
Убить псевдо-терминал
$ pkill -t pts/4
Итак, что происходит?
Хорошо, каждый вызов bashи sleepявляется вызовом функции C fork()из bashоболочки, из которой была выполнена команда.