This fork bomb always reminds me of the something an AI programming teacher said on one of the first lessons I attended "To understand recursion, first you must understand recursion".
At it's core, this bomb is a recursive function. In essence, you create a function, which calls itself, which calls itself, which calls itself.... until system resources are consumed. In this specific instance, the recursion is amplified by the use of piping the function to itself AND backgrounding it.
I've seen this answered over on StackOverflow, and I think the example given there illustrates it best, just because it's easier to see what it does at a glance (stolen from the link above...)
☃(){ ☃|☃& };☃
Define the bug function ☃() { ... }
, the body of which calls itself (the bug function), piping the output to itself (the bug function) ☃|☃
, and background the result &
. Then, after the function is defined, actually call the bug function, ; ☃
.
I note that at least on my Arch VM, the need to background the process is not a requirement to have the same end result, to consume all available process space and render the host b0rked. Actually now I've said that it seems to sometimes terminate the run away process and after a screenful of -bash: fork: Resource temporarily unavailable
it will stop with a Terminated
(and journalctl
shows bash core dumping).
To answer your question about csh/tcsh, neither of those shells support functions, you can only alias. So for those shells you'd have to write a shell script which calls itself recursively.
zsh seems to suffer the same fate (with the same code), does not core dump and causes Arch to give Out of memory: Kill process 216 (zsh) score 0 or sacrifice child.
, but it still continues to fork. After a while it then states Killed process 162 (systemd-logind) ...
(and still continues to have a forking zsh).
Arch doesn't seem to have a pacman
version of ksh, so I had to try it on debian instead. ksh objects to :
as a function name, but using something - say b()
instead seems to have the desired result.
Chet Ramey (Bash maintainer) says
There was extensive discussion about namerefs on bug-bash earlier this
year. I have a reasonable suggestion about how to change this behavior,
and I will be looking at it after bash-4.4 is released.
In the meanwhile, I'm resorting to slightly obfuscate the names of my local nameref variables, so that they don't clash within the library nor (hopefully) with global shell variable names.
In bash
5.0, this is ever so slightly remedied (but not really fixed). The following is the observed behaviour:
$ foo () { typeset -n var="$1"; echo "$var"; }
$ var=hello
$ foo var
bash: typeset: warning: var: circular name reference
bash: warning: var: circular name reference
bash: warning: var: circular name reference
hello
This shows that it works, but that there also are are a few warnings.
The relevant NEWS entry says
i. A nameref name resolution loop in a function now resolves to a variable by
that name in the global scope.
Best Answer
It's really a function named
module
. It appears in environment variables when you export a function.From bash documentation - export: