Как работает "while (sleep 100 &!); Done" в zsh и как его можно воспроизвести в bash? - PullRequest
14 голосов
/ 22 февраля 2009

В соответствии с Википедией , форк-бомба :(){ :|:& };: может быть остановлена ​​командой zsh while (sleep 100 &!) do; done, которая предположительно будет вызывать 100 спящих процессов до тех пор, пока все процессы форк-бомбы не исчезнут. Это похоже на магию; как это работает? Мне особенно любопытно, что именно "&!" означает.

Как будет выглядеть эквивалентная команда в bash?

Ответы [ 4 ]

11 голосов
/ 22 февраля 2009

Причина того, что вилочная бомба работает, заключается в том, что существует ограниченное число процессов, которые могут быть запущены одновременно, и вилочная бомба предназначена для заполнения этого предела.

Поскольку предоставленный вами код ветвления бомбы умирает, если он не может порождать дочерний процесс, родительские процессы фактически не задерживаются, но тот факт, что дети продолжают создавать новых великих * детей, сохраняет таблицу процессов заполненной.

Таким образом, решение для сна спроектировано так, что оно может проникнуть в некоторые процессы, которые просто спят в течение короткого периода времени, и для каждого процесса сна, который удается создать, происходит меньше разветвлений. В конце концов, процессы сна сами заполняют таблицу процессов, и бомбы разветвляются.

Как только таблица процессов заполнится из спящих процессов, цикл while может быть прерван, а спящие процессы прекратятся, когда истечет их время ожидания. Проблема решена .

Как уже упоминалось, важной частью команды zsh является запуск в фоновом режиме &, поэтому команда bash будет в основном такой же, как и в других ответах:

while (sleep 100 &) do; done

Я не думаю, что часть nohup / ! важна, если вы не хотите выходить из системы во время сна, но я был бы рад, если я буду прямо, если я ошибаюсь.

8 голосов
/ 22 февраля 2009

Сначала можно написать вилочную бомбу:

foo()
{
    foo|foo&
}
foo

Что делает это немного понятнее - каждая итерация запускает два подпроцесса, а затем умирает. Так что, если вилка не удастся, она не будет зависать.

Поэтому все, что мы должны сделать, - это временно прекратить разветвление. Таким образом, мы создаем процессы, которые спят на 100 и занимают пространство процессов, как это делают процессы сна.

Zsh &! похож на &, но отвергает новый процесс (не завершает его при выходе из системы) - это, вероятно, не важно в этом примере. ( руководство ) Может быть заменено на nohup.

Поэтому bash:

while (nohup sleep 100 &) do; done

должно работать.

6 голосов
/ 28 июня 2009

Я парень, который написал эту часть статьи в Википедии (и который "открыл" это лекарство после случайного запуска вилочной бомбы в моей системе!).

Причина "&!" вместо «&» это действительно означает, что zsh не может контролировать работу нового процесса, то есть пытаться понять, когда и когда он закончится. Я не помню точно, почему контроль работы был проблемой, когда я попробовал это, но это было. Вы можете попробовать это, чтобы увидеть, как работает «лечение» и что происходит, если вы не препятствуете контролю за работой. Возможно, проблема с контролем заданий была связана с некоторой ошибкой в ​​zsh, которой даже нет в bash, и, возможно, она больше не актуальна в zsh.

Так что попробуйте просто "&" с bash, и если управление заданиями мешает, попробуйте отключить его ("set + m"), и, надеюсь, это сработает.

Вы правы, что статья в Википедии, вероятно, не должна зависеть от zsh.

2 голосов
/ 22 февраля 2009

Очень интересный вопрос!

Согласно этой статье в Википедии, цель полной команды - создать множество безобидных заданий, которые отключат вилочную бомбу, потому что она больше не сможет порождать даже больше детей.

Согласно инструкции zsh ,

Если работа начинается с &|' or &! ', тогда эта работа сразу же отменяется. После запуска у него нет место в рабочем столе, а не с учетом функций контроля работы описано здесь.

Я не уверен, как добиться того же с bash. Однако может подойти что-то вроде следующего:

nohup sleep 100 &
...