GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Wo ist die Gabel () auf der Gabelbombe :(){ :|:&};:?

Als Ergebnis der Pipe in x | y , wird eine Subshell erstellt, die die Pipeline als Teil der Prozessgruppe im Vordergrund enthält. Dadurch werden weiterhin Subshells erstellt (über fork() ) auf unbestimmte Zeit, wodurch eine Gabelbombe entsteht.

$ 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

Der Fork tritt jedoch erst dann auf, wenn der Code ausgeführt wird, was der letzte Aufruf von : ist in Ihrem Code.

So zerlegen Sie die Funktionsweise der Gabelbombe:

  • :() - Definieren Sie eine neue Funktion namens :
  • { :|: & } - eine Funktionsdefinition, die die aufrufende Funktion rekursiv im Hintergrund in eine andere Instanz der aufrufenden Funktion leitet
  • : - Fork-Bomb-Funktion aufrufen

Dies ist in der Regel nicht zu speicherintensiv, saugt aber PIDs auf und verbraucht CPU-Zyklen.


Das letzte Bit des Codes, ;: führt die Funktion :(){ ... } aus . Hier tritt der Fork auf.

Das Semikolon beendet den ersten Befehl, und wir beginnen einen weiteren, d. h. den Aufruf der Funktion : . Die Definition dieser Funktion beinhaltet einen Aufruf an sich selbst (: ) und die Ausgabe dieses Aufrufs wird an eine Hintergrundversion : geleitet . Dies stützt den Prozess auf unbestimmte Zeit.

Jedes Mal, wenn Sie die Funktion :() aufrufen Sie rufen die C-Funktion fork() auf . Letztendlich werden dadurch alle Prozess-IDs (PIDs) auf dem System erschöpft.

Beispiel

Sie können den |:& austauschen mit etwas anderem, damit Sie sich ein Bild davon machen können, was vor sich geht.

Richten Sie einen Beobachter ein

Tun Sie dies in einem Terminalfenster:

$ watch "ps -eaf|grep \"[s]leep 61\""

Stellen Sie die Gabelbombe mit "Sicherung verzögert" ein

In einem anderen Fenster führen wir eine leicht modifizierte Version der Gabelbombe aus. Diese Version wird versuchen, sich selbst zu drosseln, damit wir untersuchen können, was sie tut. Unsere Version schläft 61 Sekunden lang, bevor sie die Funktion :() aufruft .

Außerdem werden wir auch den ersten Aufruf in den Hintergrund stellen, nachdem er aufgerufen wurde. Strg + z , und geben Sie dann bg ein .

$ :(){ sleep 61; : | : & };:

# control + z
[1]+  Stopped                 sleep 61
[2] 5845
$ bg
[1]+ sleep 61 &

Wenn wir jetzt jobs ausführen Befehl im Anfangsfenster sehen wir Folgendes:

$ jobs
[1]-  Running                 sleep 61 &
[2]+  Running                 : | : &

Nach ein paar Minuten:

$ jobs
[1]-  Done                    sleep 61
[2]+  Done                    : | :

Beim Beobachter einchecken

In der Zwischenzeit im anderen Fenster, in dem wir watch ausführen :

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

Prozesshierarchie

Und ein ps -auxf zeigt diese Prozesshierarchie:

$ 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
...
...

Aufräumzeit

Ein killall bash wird die Dinge stoppen, bevor sie außer Kontrolle geraten. Das Aufräumen auf diese Weise kann ein wenig schwerfällig sein, eine freundlichere, sanftere Art, die möglicherweise nicht jeden bash zerreißt Shell down, wäre folgendes zu tun:

  1. Bestimmen Sie, in welchem ​​Pseudo-Terminal die Gabelbombe laufen soll

    $ tty
    /dev/pts/4
    
  2. Beenden Sie das Pseudo-Terminal

    $ pkill -t pts/4
    

Also, was ist los?

Nun, jeder Aufruf von bash und sleep ist ein Aufruf der C-Funktion fork() aus dem bash Shell, von der aus der Befehl ausgeführt wurde.


Linux
  1. Wo ist das Cron/Crontab-Protokoll? / Wie aktiviere ich das Cron-Protokoll?

  2. Wie funktioniert eine Gabelbombe?

  3. Warum ist der Standardprozesserstellungsmechanismus Fork?

  4. Wohin gehen Dateien, wenn der Rm-Befehl ausgegeben wird?

  5. Wo ist die Inittab-Datei?

Unzip glaubt, dass die Zip-Datei eine Zip-Bombe ist?

Wo ist die Itoa-Funktion in Linux?

Wo ist die php.ini-Datei auf einem Linux/CentOS-PC?

Wo ist die x86-64 System V ABI dokumentiert?

Wo befindet sich das Dateisystem des Linux-Subsystems in Windows 10?

Wo ist die Terminalansicht von tty7