Warning: Running this command in most shells will result in a broken system that will need a forced shutdown to fix
I understand the recursive function :(){ :|: & };: and what it does. But I don’t know where is the fork system call. I’m not sure, but I suspect in the pipe |.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
As a result of the pipe in x | y, a subshell is created to contain the pipeline as part of the foreground process group. This continues to create subshells (via fork()) indefinitely, thus creating a fork bomb.
$ for (( i=0; i<3; i++ )); do > echo "$BASHPID" > done 16907 16907 16907 $ for (( i=0; i<3; i++ )); do > echo "$BASHPID" | cat > done 17195 17197 17199
The fork does not actually occur until the code is run, however, which is the final invocation of : in your code.
To disassemble how the fork bomb works:
:()– define a new function called:{ :|: & }– a function definition that recursively pipes the calling function into another instance of the calling function in the background:– call the fork bomb function
This tends to not be too memory intensive, but it will suck up PIDs and consume CPU cycles.
Method 2
The last bit of the code, ;: is running the function :(){ ... }. This is where the fork is occurring.
The semicolon terminates the first command, and we’re starting another one, i.e. invoking the function :. The definition of this function includes a call to itself (:) and the output of this call is piped to a backgrounded version :. This props up the process indefinitely.
Every time you’re calling the function :() you’re calling the C function fork(). Eventually this will exhaust all the process IDs (PIDs) on the system.
Example
You can swap out the |:& with something else so you can get an idea of what’s going on.
Setup a watcher
In one terminal window do this:
$ watch "ps -eaf|grep "[s]leep 61""
Setup the “fuse delayed” fork bomb
In another window we’ll run a slightly modified version of the fork bomb. This version will attempt to throttle itself so we can study what it’s doing. Our version will sleep for 61 seconds before calling the function :().
Also we’ll background the initial call as well, after it’s invoked. Ctrl + z, then type bg.
$ :(){ sleep 61; : | : & };:
# control + z
[1]+ Stopped sleep 61
[2] 5845
$ bg
[1]+ sleep 61 &
Now if we run the jobs command in the initial window we’ll see this:
$ jobs [1]- Running sleep 61 & [2]+ Running : | : &
After a couple of minutes:
$ jobs [1]- Done sleep 61 [2]+ Done : | :
Check in with the watcher
Meanwhile in the other window where we’re running watch:
Every 2.0s: ps -eaf|grep "[s]leep 61" Sat Aug 31 12:48:14 2013 saml 6112 6108 0 12:47 pts/2 00:00:00 sleep 61 saml 6115 6110 0 12:47 pts/2 00:00:00 sleep 61 saml 6116 6111 0 12:47 pts/2 00:00:00 sleep 61 saml 6117 6109 0 12:47 pts/2 00:00:00 sleep 61 saml 6119 6114 0 12:47 pts/2 00:00:00 sleep 61 saml 6120 6113 0 12:47 pts/2 00:00:00 sleep 61 saml 6122 6118 0 12:47 pts/2 00:00:00 sleep 61 saml 6123 6121 0 12:47 pts/2 00:00:00 sleep 61
Process hierarchy
And a ps -auxf shows this process hierarchy:
$ ps -auxf saml 6245 0.0 0.0 115184 5316 pts/2 S 12:48 0:00 bash saml 6247 0.0 0.0 100988 468 pts/2 S 12:48 0:00 _ sleep 61 .... .... saml 6250 0.0 0.0 115184 5328 pts/2 S 12:48 0:00 bash saml 6268 0.0 0.0 100988 468 pts/2 S 12:48 0:00 _ sleep 61 saml 6251 0.0 0.0 115184 5320 pts/2 S 12:48 0:00 bash saml 6272 0.0 0.0 100988 468 pts/2 S 12:48 0:00 _ sleep 61 saml 6252 0.0 0.0 115184 5324 pts/2 S 12:48 0:00 bash saml 6269 0.0 0.0 100988 464 pts/2 S 12:48 0:00 _ sleep 61 ... ...
Clean up time
A killall bash will stop things before they get out of hand. Doing your clean up this way may be a little heavy handed, a kinder gentler way which won’t potentially tear every bash shell down, would be to do the following:
-
Determine what pseudo terminal the fork bomb is going to run in
$ tty /dev/pts/4
-
Kill the pseudo terminal
$ pkill -t pts/4
So what’s going on?
Well each invocation of bash and sleep is a call to the C function fork() from the bash shell from where the command was run.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0