
Я настроил тестовую виртуальную машину, чтобы проверить эффект форк-бомб. Поэтому я отредактировал limits.conf
следующее для root
пользователя:
root hard nproc 512
Теперь я бросаю вот такую вилочную бомбу:
:(){ :|:& };:
После этого, через некоторое время (которое, как я полагаю, требуется для достижения предела в 512), появляется следующая ошибка:
Это продолжается без остановки. Можно ли как-то остановить это без перезагрузки машины?
решение1
Можно ли как-то это остановить, не перезагружая машину?
Это не совсем невозможно, и вы можете сделать это с помощью удачи — то есть, вам удастся завершить все процессы до того, как будет создан другой. 1 Но вам должно очень-очень повезти, так что это ненадежная и не стоящая усилий попытка.[может быть, slm повезло больше, чем мне, лол -- честно говоря, я не особо старался]. Если вы поиграете с приоритетами, ваши шансы могут улучшиться (см. man nice
), хотя я подозреваю, что это также снизит эффективность форк-бомбы.
Лучшей идеей может быть использование того, что истекает по времени. Пример на языке C см. в сноске 5 кмой ответ здесь2 Вы можете сделать то же самое с помощью скрипта оболочки, хотя это будет не так коротко :(){ :|:& };:
:
#!/bin/bash
export fbomb_duration=$1
export fbomb_start=$(date +%s)
go () {
now=$(date +%s)
if [[ $(($now-$fbomb_start)) -gt $fbomb_duration ]]
then exit 0;
fi
go &
}
while ((1)); do
go
done
Выполнить это с одним аргументом, числом секунд. Все форки умрут после этого времени.
1 На самом деле, это может произойти само по себе, в конце концов, если убийце OOM ядра повезет. Но не задерживайте дыхание.
2 Метод, используемый там для подрезки этой конкретной бомбы (путем установки vm.overcommit_memory=2
), почти наверняка не будет работать в общем случае, но вы можете попробовать. Я нет, так как я хотел бы оставить свою систему работающей на данный момент ;)
решение2
При разработке ответа на этот вопрос под названием:Где находится fork() в fork-бомбе :(){ :|: & };:?, я собрал то, что назвал бомбой замедленного действия, которую было легче уничтожить.
Кроме того, разрабатывая этот ответ, я регулярно мог остановить форк-бомбу, убивая все процессы. Это было проще и более повторяемо, чем я ожидал.
Используемые методы
Прошло много времени с тех пор, как я писал этот ответ, поэтому сейчас я не уверен на 100%, но навскидку мне кажется, что я использовал этот метод:
$ pkill -f :
Он немного замер в ожидании процесса, но в конце концов смог запуститься. Также я бы запомнил идентификатор родительского процесса перед запуском fork bomb и сделал бы это тоже:
$ pkill -P <PPID>
Это идентификатор родительского процесса (PPID), с которого была запущена fork-бомба. Этот метод отключил бы все дочерние процессы, что привело бы к их каскадному запуску и завершению.
решение3
Я считаю, что вы могли бы сделать так, как предложено в ответездесьпри условии, что у вас есть доступ к shell.
killall -STOP -u user1
killall -KILL -u user1