叉子炸弹是如何工作的?

叉子炸弹是如何工作的?
  • 警告请勿尝试在生产机器上运行此程序

在阅读中有关该主题的维基百科页面我通常遵循以下代码发生的情况:

:(){ :|:& };:

描述摘录

下面的叉子炸弹于 2002 年作为艺术品展出;56 它的确切来源尚不清楚,但它在 2002 年之前就存在于 Usenet 上。该炸弹是通过将以下 13 个字符粘贴到 UNIX系统外壳如巴什或者桀骜。它通过定义一个名为“:”的函数来运行,该函数调用自身两次,一次在前台,一次在后台。

然而,最后一点对我来说并不完全清楚。我看到函数定义:

:(){ ... }

但还发生了什么?其他 shell(例如kshcsh、 )tcsh是否也遭受同样的命运,能够构造类似的东西?

答案1

这个fork炸弹总是让我想起人工智能编程老师在我参加的第一堂课上所说的话“要理解递归,首先你必须理解递归”。

从本质上讲,这枚炸弹是递归的功能。本质上,您创建一个函数,它调用自身,它调用自身,它调用自身......直到系统资源被消耗。在这个特定的实例中,通过使用管道将函数传递给自身并将其置于后台来放大递归。

我已经看到这个答案了堆栈溢出,我认为那里给出的例子最好地说明了这一点,只是因为更容易一目了然地看到它的作用(从上面的链接中窃取......)

☃(){ ☃|☃& };☃

定义 bug 函数☃() { ... },其主体调用自身(bug 函数),通过管道将输出传递给自身(bug 函数) ☃|☃,并将结果置于后台&。然后,在函数定义之后,实际调用bug函数,; ☃

我注意到,至少在我的 Arch VM 上,将进程置于后台的需要并不要求具有相同的最终结果,即消耗所有可用的进程空间并渲染主机 b0rked。实际上,现在我已经说过,它似乎有时会终止失控进程,并且在一屏之后-bash: fork: Resource temporarily unavailable会以 a 停止Terminated(并journalctl显示 bash 核心转储)。

要回答有关 csh/tcsh 的问题,这些 shell 都不支持函数,您只能使用别名。因此,对于这些 shell,您必须编写一个递归调用自身的 shell 脚本。

zsh 似乎遭受了同样的命运(使用相同的代码),不会核心转储并导致 Arch 给出Out of memory: Kill process 216 (zsh) score 0 or sacrifice child.,但它仍然继续分叉。过了一会儿,它就会声明Killed process 162 (systemd-logind) ...(并且仍然继续有一个分叉 zsh)。

Arch 似乎没有pacmanksh 版本,所以我不得不在 debian 上尝试一下。 ksh 反对将其:作为函数名称,但使用某些东西 - sayb()似乎可以达到预期的结果。

相关内容