Come funziona "mentre (il sonno 100 &!) do; fatto" work in zsh, e come potrebbe essere replicato in bash?


14

Secondo Wikipedia, il forkbomb :(){ :|:& };: può essere fermato con il comando zsh while (sleep 100 &!) do; done, che sarà presumibilmente di spawn sonno 100 processi fino . tutti i processi forkbomb sono andati Questo mi sembra magia;?. come funziona sono particolarmente curioso di sapere esattamente che cosa "! &" significa

Cosa sarebbe un look comando equivalente come in bash

11

Il motivo per cui una bomba a forcella funziona è perché esiste un limite limitato al numero di processi che possono essere eseguiti in qualsiasi momento e una bomba a forcella è progettata per colmare questo limite.

Poiché il codice forkbomb fornito muore se non è in grado di generare un processo figlio, i processi parent non si bloccano, ma il fatto che i bambini continuino a creare nuovi * grandi bambini mantiene la tabella del processo piena.

Quindi la soluzione di sonno è progettata per introdursi in alcuni processi che dormono solo per un breve periodo di tempo, e per ogni processo di sonno che riesce a essere creato, ci sono meno bombe a forcella che si verificano. Alla fine i processi del sonno riempiono il tavolo proces e le bomba a forcella si spengono.

Una volta che la tabella di processo è piena, i processi di sospensione del ciclo while possono essere interrotti e i processi di sospensione moriranno una volta trascorso il tempo di sospensione. Problema risolto.

Come già accennato la parte importante del comando zsh è il run-in-fondo &, in modo che il comando bash sarebbe fondamentalmente lo stesso come indicato nelle altre risposte:

while (sleep 100 &) do; done 

I don Penso che la parte nohup/! sia importante a meno che non si desideri disconnettersi entro il tempo di sospensione, ma sarei felice di essere impostato correttamente se sbaglio.


2

? Domanda molto interessante!

Secondo l'articolo di Wikipedia, lo scopo del comando completo è creare molti lavori innocui che disabilitino la bomba a forcella perché non sarà più in grado di generare ancora più bambini.

Secondo il zsh manual,

Se un processo viene avviato con &|' or &!', allora che lavoro è subito rinnegato. Dopo l'avvio, non ha una posizione nella tabella di lavoro e non è soggetto alle caratteristiche di controllo lavoro descritte qui.

Non sono sicuro di come ottenere lo stesso con bash. Tuttavia, qualcosa di simile al seguente potrebbe fare:

nohup sleep 100 & 

8

Prima la bomba forcella si può scrivere:

foo() 
{ 
    foo|foo& 
} 
foo 

che lo rende un po 'più chiaro - ogni iterazione inizia due sottoprocessi, poi muore. Quindi se la biforcazione fallisce, non si blocca.

Quindi tutto ciò che dobbiamo fare è rendere il bivio temporaneamente fallito. Così creiamo processi che dormono 100 e occupano lo spazio del processo, come fanno i processi del sonno.

Lo zsh &! è come & ma rinnega il nuovo processo (non lo elimina al momento della disconnessione), probabilmente non è importante in questo esempio. (manual) Può essere sostituito con nohup.

Quindi la bash:

while (nohup sleep 100 &) do; done 

dovrebbe funzionare.


6

Sono il ragazzo che ha scritto quella parte dell'articolo di Wikipedia (e che ha "scoperto" questa cura dopo aver accidentalmente avviato la bomba a forcella sul mio sistema!).

Il motivo per "&!" invece di "&" è in effetti per impedire a zsh di eseguire il controllo del lavoro sul nuovo processo, cioè, cercando di preoccuparsi di quando e se è finito. Non ricordo esattamente perché il controllo dei lavori è stato un problema quando l'ho provato, ma lo è stato. Puoi effettivamente provarlo per vedere come funziona la "cura" e cosa succede se non impedisci il controllo del lavoro. Forse il problema con il controllo dei lavori ha a che fare con qualche bug in zsh che non esiste nemmeno in bash, e forse non è più rilevante nemmeno in zsh.

Quindi provate solo un "&" con bash, e se il controllo del lavoro sta interferendo, provate a disabilitarlo ("set + m") e speriamo che funzioni.

Hai ragione che l'articolo di Wikipedia non dovrebbe probabilmente essere dipendente da zsh.