Wie funktioniert „während (Schlaf 100 &!) do; getan“ work in zsh, und wie könnte es in bash repliziert werden?


14

Nach Wikipedia, die forkbomb :(){ :|:& };: mit dem zsh Befehl while (sleep 100 &!) do; done, die angeblich Laich Schlaf 100 Prozesse gestoppt werden, bis . alle forkbomb Prozesse sind weg Dies scheint wie Magie;?., wie es funktioniert ich bin besonders gespannt, genau das, was „! &“ bedeutet

Was wäre ein äquivalenter Befehl aussehen wie in bash

11

Der Grund, warum eine Gabelzange funktioniert, liegt darin, dass es eine endliche Grenze für die Anzahl der Prozesse gibt, die gleichzeitig ausgeführt werden können, und eine Gabelzange ist dafür ausgelegt, diese Grenze zu füllen.

Da der von Ihnen angegebene Forkbomb-Code stirbt, wenn er keinen Child-Prozess erzeugen kann, bleiben die Parent-Prozesse nicht hängen, aber die Tatsache, dass die Kinder weiterhin neue Grand * -Children erstellen, hält die Prozesstabelle voll.

Also die Schlaf-Lösung ist so konzipiert, dass sie sich in einige Prozesse schleicht, die nur für eine kurze Zeit schlafen, und für jeden Schlafprozess, der geschaffen wird, gibt es weniger Gabel-Bomben. Schließlich füllen die Schlafprozesse den Prozesstisch selbst und die Gabelbomben sterben ab.

Sobald die Prozesstabelle voll ist, kann die while-Schleife beendet werden und die Schlafprozesse werden beendet, sobald die Schlafzeit abgelaufen ist. Problem gelöst.

Wie bereits den wichtigen Teil des zsh Befehl erwähnt ist der Run-in-Hintergrund &, so würde die Bash-Befehl sein im Grunde die gleiche wie in den anderen Antworten gegeben:

while (sleep 100 &) do; done 

I don Ich denke, dass der nohup/ Teil wichtig ist, es sei denn, Sie möchten sich innerhalb der Ruhezeit ausloggen, aber ich würde mich freuen, wenn ich falsch liege.


2

? Sehr interessante Frage!

Laut diesem Wikipedia-Artikel besteht der Zweck des vollständigen Befehls darin, viele harmlose Jobs zu erstellen, die die Gabel-Bombe deaktivieren, weil sie nicht mehr in der Lage ist, noch mehr Kinder zu spawnen.

Nach dem zsh manual,

Wenn ein Job mit &|' or & gestartet wird!‘, dann wird dieser Job sofort verleugnet. Nach dem Start hat es keinen Platz in der Jobtabelle und ist nicht , abhängig von den hier beschriebenen Jobsteuerungsfunktionen .

Ich bin mir nicht sicher, wie man dasselbe mit bash erreicht. Doch so etwas wie das folgende tun könnte:

nohup sleep 100 & 

8

Zuerst wird die Gabel Bombe kann geschrieben werden:

foo() 
{ 
    foo|foo& 
} 
foo 

, die es ein wenig klarer macht - jeder Iteration beginnt zwei Teilprozesse, dann stirbt. Wenn also die Gabelung fehlschlägt, wird es nicht herumhängen.

Daher müssen wir nur die Gabelung vorübergehend scheitern lassen. So schaffen wir Prozesse, die 100 schlafen und Prozessraum belegen, wie die Schlafprozesse.

Die zsh &! ist wie & aber verleugnet den neuen Prozess (tötet es nicht beim Abmelden) - es ist wahrscheinlich nicht wichtig in diesem Beispiel. (manual) Es kann durch nohup ersetzt werden.

Deshalb ist die bash:

while (nohup sleep 100 &) do; done 

funktionieren sollte.


6

Ich bin der Typ, der diesen Teil des Wikipedia-Artikels geschrieben hat (und der diese Kur "entdeckte", nachdem er versehentlich die Gabelbombe auf meinem System gestartet hatte!).

Der Grund für die "&!" anstelle von "&" ist in der Tat zu verhindern, dass zsh Job-Kontrolle über den neuen Prozess, d. h. zu versuchen, zu kümmern, wann und wenn es fertig ist. Ich erinnere mich nicht genau, warum Jobkontrolle ein Problem war, als ich es versuchte, aber es war. Sie können es tatsächlich ausprobieren, um zu sehen, wie die "Heilung" funktioniert und was passiert, wenn Sie die Jobkontrolle nicht verhindern. Vielleicht hatte das Problem mit der Jobsteuerung etwas mit einem Fehler in zsh zu tun, der nicht einmal in bash existiert, und vielleicht ist er auch in zsh nicht mehr relevant.

Also versuchen Sie einfach eine "&" mit bash, und wenn Job-Kontrolle stört, versuchen Sie es zu deaktivieren ("set + m") und hoffentlich würde das funktionieren.

Sie haben Recht, dass der Wikipedia-Artikel wahrscheinlich nicht zsh-abhängig sein sollte.