Co oznacza to tajemnicze polecenie Bash?

23

Czytałem ostrzeżenie forum Ubuntu o złośliwych poleceniach i znalazłem ten interesujący klejnot:

:(){ :|:& };:

OSTRZEŻENIE: Powyższy kod spowoduje awarię komputera, chyba że masz ścisłe limity procesowe (których prawdopodobnie nie masz), które wymagają twardego restartu.

Rozważ ten kod podobny do uruchamiania sudo rm -rf /.

Ale co to znaczy? Nawet z moim doświadczeniem w programowaniu nigdy nie widziałem tak tajemniczego polecenia, które nie jest językiem asemblera.

TheLQ
źródło
16
Dodatkowa uwaga: tak naprawdę w niczym nie przypomina sudo rm -rf /. To polecenie usuwa wszystkie twoje pliki; ten tylko zatyka zasoby komputera, dopóki nie stanie się bezużyteczny i będziesz musiał ponownie uruchomić.
jtbandes
@jtban: Następnie edytuj. Oba fragmenty kodu można uruchomić, uważając je za „niebezpieczne”. Tak, sudo rm -rf /jest bardziej niebezpieczne, ale widziałem, jak ludzie wykonują to na zdalnych serwerach „chciałem tylko zobaczyć, co to zrobiło”, gdzie trudno jest zrestartować komputer bez dostępu do panelu sterowania.
Josh K
7
jego emotibomb: P
RCIX
Zauważ, że może być arbitrary_name(){ arbitrary_name|arbitrary_name& };arbitrary_name. Nazwa :nie tylko sprawia, że ​​to polecenie jest krótkie i tajemnicze, ale także zamienia :wbudowane narzędzie, które nic nie robi, w funkcję, która dużo robi . Jeśli zakradniesz jego definicję :(){ :|:& }do czyjegoś środowiska i pozwolisz mu pozostać, uderzy, gdy ofiara najmniej się tego spodziewa .
Kamil Maciorowski

Odpowiedzi:

40

To, jak powiedziałeś, widełka. To, co robi, to zdefiniowanie funkcji, a następnie wywołanie jej. Funkcja jest wywoływana :.

Nazwijmy to forkbomb, abyśmy mogli lepiej zobaczyć, co się dzieje:

forkbomb(){ forkbomb|forkbomb& };forkbomb

Jak widać i zapewne zgadujesz z doświadczenia w programowaniu, pierwsza część to definicja funkcji ( forkbomb(){ ... }), a ostatnia :to wywołanie funkcji (po ;prostu rozdziela instrukcje w Bash).

Co teraz robi ta funkcja? Jeśli znasz Bash, będziesz wiedział, że |postać przesyła standardowe wyjście jednego polecenia / programu do standardowego wejścia innego. Zasadniczo :|:uruchamia dwa wystąpienia funkcji (w tym miejscu „rozwidla”).

A potem magia: &umieszcza te polecenia w tle, pozwalając na powrót oryginalnej funkcji, podczas gdy każde wystąpienie powoduje, że krowy wracają do domu w tle, zużywając wszystkie zasoby i usuwając system (chyba że ma ograniczenia narzucone).

jtbandes
źródło
1
Świetna odpowiedź! Nie zdawałem sobie sprawy, że możesz użyć: jako nazwy funkcji. Zmiana nazwy pomaga. Przyjmie za 3 minuty.
TheLQ
1
+1 Cool ... Świetne wyjaśnienie. To jest jak przepełnienie stosu dla przełącznika zadań systemu operacyjnego. Czy faktycznie powoduje awarię jądra, czy po prostu pochłania zasoby, dopóki nie stanie się zbyt nie do zniesienia?
Evan Plaice,
Nie sądzę, że faktycznie powoduje awarię jądra, przynajmniej nie bezpośrednio. Po prostu tworzy wykładniczo więcej procesów, z których każdy zajmuje procesor i pamięć, a gdy procesor próbuje obsłużyć je wszystkie, korzystanie z nich staje się naprawdę niemożliwe. Może się zdarzyć, że jądro ostatecznie ulegnie awarii pod obciążeniem (nie jestem pewien), ale do tego czasu będzie bezużyteczne.
jtbandes
3
Nie zapomnij wyjaśnić finału :, który faktycznie wykonuje funkcję!
Phoshi,
@ Phoshi: myślałem, że tak, ale zredaguję, aby wyjaśnić!
jtbandes
9

Zaczerpnięte z artykułu w Wikipedii Forkbomb :

:()      # define ':' -- whenever we say ':', do this:
{        # beginning of what to do when we say ':'
    :    # load another copy of the ':' function into memory...
    |    # ...and pipe its output to...
    :    # ...another copy of ':' function, which has to be loaded into memory
         # (therefore, ':|:' simply gets two copies of ':' loaded whenever ':' is called)
    &    # disown the functions -- if the first ':' is killed,
         #     all of the functions that it has started should NOT be auto-killed
}        # end of what to do when we say ':'
;        # Having defined ':', we should now...
:        # ...call ':', initiating a chain-reaction: each ':' will start two more.
James T.
źródło
7

Zepsuty:

: () // Define ':' as a function. When you type ':' do the following
{
    : // Call ':' 
    | // Redirect output
    : // Into ':'
    & // Push process to the background
}; // End of ':' def
: // Now do ':'

Zmień :na bombi masz:

bomb(){ bomb|bomb& };bomb

To jest naprawdę dość eleganckie.

Josh K.
źródło