我设置了测试VM来测试fork炸弹的效果。所以我为用户编辑limits.conf
如下:root
root hard nproc 512
现在我像这样扔下一个叉子炸弹:
:(){ :|:& };:
之后,过了一段时间(我相信需要达到 512 限制),出现以下错误:
这种情况持续不断。有什么办法可以在不重新启动机器的情况下停止此操作吗?
答案1
有什么办法可以在不重新启动机器的情况下停止此操作吗?
这并非完全不可能,您可以通过运气来做到这一点——也就是说,您可以在另一个进程产生之前设法杀死所有进程。1 但你必须非常非常幸运,所以这不是一个可靠或值得的努力[也许 slm 比我幸运,哈哈——说实话,我还没那么努力]。如果您考虑优先级,您的机会可能会提高(请参阅参考资料man nice
),尽管我怀疑这也会影响叉子炸弹的功效。
更好的想法可能是使用超时的方法。对于 C 语言的示例,请参见脚注 5我的回答在这里。2 您可以使用 shell 脚本执行相同的操作,尽管不会那么短:(){ :|:& };:
:
#!/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() 在哪里:(){ :|: & };:?,我组装了一个我称之为导火索延迟叉炸弹的东西,更容易杀死。
此外,在开发这个答案时,我经常能够通过终止所有进程来阻止叉子炸弹。它比我预想的更容易、更可重复。
使用的方法
自从我写这个答案以来已经有一段时间了,所以我现在不能 100% 确定,但我突然想到我正在使用这种方法:
$ pkill -f :
它会停滞一段时间等待进程,但最终它能够运行。另外,我会在启动 fork 炸弹之前记下父进程 ID,并且也会这样做:
$ pkill -P <PPID>
这是运行 fork 炸弹的父进程 ID (PPID)。该方法将关闭所有子进程,这将导致它们全部级联并死亡。
答案3
我相信你可以按照答案中的建议进行操作这里假设您有权访问 shell。
killall -STOP -u user1
killall -KILL -u user1