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

Bash:unendlicher Schlaf (unendliches Blockieren)

tail blockiert nicht

Wie immer gilt:Auf alles gibt es eine Antwort, die kurz, leicht verständlich, leicht nachvollziehbar und komplett falsch ist. Hier tail -f /dev/null fällt in diese Kategorie;)

Betrachtet man es mit strace tail -f /dev/null Sie werden feststellen, dass diese Lösung weit davon entfernt ist zu blockieren! Wahrscheinlich sogar noch schlimmer als sleep Lösung in der Frage, da es (unter Linux) wertvolle Ressourcen wie inotify verwendet System. Auch andere Prozesse, die in /dev/null schreiben machen Sie tail Schleife. (Auf meinem Ubuntu64 16.10 fügt dies einem bereits ausgelasteten System mehrere 10 Syscalls pro Sekunde hinzu.)

Die Frage war nach einem Sperrbefehl

So etwas gibt es leider nicht ..

Lesen:Ich kenne keine Möglichkeit, dies direkt mit der Shell zu archivieren.

Alles (sogar sleep infinity ) kann durch irgendein Signal unterbrochen werden. Wenn Sie also wirklich sicher sein wollen, dass es nicht ausnahmsweise zurückkehrt, muss es in einer Schleife laufen, wie Sie es bereits für Ihren sleep getan haben . Bitte beachten Sie, dass (unter Linux) /bin/sleep ist anscheinend auf 24 Tage begrenzt (siehe strace sleep infinity ), daher ist das Beste, was Sie wahrscheinlich tun können, Folgendes:

while :; do sleep 2073600; done

(Beachten Sie, dass ich sleep glaube loopt intern bei höheren Werten als 24 Tagen, das bedeutet aber:Es blockiert nicht, es loopt sehr langsam. Warum also diese Schleife nicht nach außen verschieben?)

.. aber Sie können mit einem unbenannten fifo ganz in die Nähe kommen

Sie können etwas erstellen, das wirklich blockiert, solange keine Signale an den Prozess gesendet werden. Im Folgenden wird bash 4 verwendet , 2 PIDs und 1 fifo :

bash -c 'coproc { exec >&-; read; }; eval exec "${COPROC[0]}<&-"; wait'

Ob dies wirklich blockiert, können Sie mit strace prüfen wenn du magst:

strace -ff bash -c '..see above..'

Wie dies konstruiert wurde

read blockiert, wenn keine Eingabedaten vorhanden sind (siehe einige andere Antworten). Allerdings ist die tty (auch bekannt als stdin ) ist normalerweise keine gute Quelle, da sie geschlossen wird, wenn sich der Benutzer abmeldet. Außerdem könnte es einige Eingaben von tty stehlen . Nicht schön.

Um read zu machen block, müssen wir auf so etwas wie fifo warten die niemals etwas zurückgeben wird. In bash 4 es gibt einen Befehl, der uns genau so einen fifo liefern kann :coproc . Wenn wir auch auf die Sperrung read warten (das ist unser coproc ), wir sind fertig. Leider muss dies zwei PIDs und einen fifo offen halten .

Variante mit einem benannten fifo

Wenn Sie sich nicht die Mühe machen, einen benannten fifo zu verwenden , können Sie dies wie folgt tun:

mkfifo "$HOME/.pause.fifo" 2>/dev/null; read <"$HOME/.pause.fifo"

Beim Lesen keine Schleife zu verwenden ist ein bisschen schlampig, aber Sie können diesen fifo wiederverwenden so oft Sie möchten und machen Sie den read s terminat mit touch "$HOME/.pause.fifo" (Wenn mehr als ein einzelner Lesevorgang wartet, werden alle auf einmal beendet).

Oder verwenden Sie Linux pause() Systemaufruf

Für das unendliche Blockieren gibt es einen Linux-Kernel-Aufruf namens pause() , was tut, was wir wollen:ewig warten (bis ein Signal ankommt). Allerdings gibt es dafür (noch) kein Userspace-Programm.

C

Erstellen Sie ein solches Programm ist einfach. Hier ist ein Schnipsel, um ein sehr kleines Linux-Programm namens pause zu erstellen die auf unbestimmte Zeit pausiert (benötigt diet , gcc usw.):

printf '#include <unistd.h>\nint main(){for(;;)pause();}' > pause.c;
diet -Os cc pause.c -o pause;
strip -s pause;
ls -al pause

python

Wenn Sie etwas nicht selbst kompilieren möchten, aber python haben installiert haben, können Sie diese unter Linux verwenden:

python -c 'while 1: import ctypes; ctypes.CDLL(None).pause()'

(Hinweis:Verwenden Sie exec python -c ... Um die aktuelle Shell zu ersetzen, wird eine PID freigegeben. Die Lösung kann auch durch einige IO-Umleitungen verbessert werden, wodurch ungenutzte FDs freigegeben werden. Dies liegt an Ihnen.)

Wie das funktioniert (glaube ich):ctypes.CDLL(None) lädt die Standard-C-Bibliothek und führt pause() aus funktionieren darin innerhalb einer zusätzlichen Schleife. Weniger effizient als die C-Version, aber funktioniert.

Meine Empfehlung für Sie:

Bleiben Sie im Schleifenschlaf. Es ist einfach zu verstehen, sehr portabel und blockiert die meiste Zeit.


sleep infinity macht genau das, was es vorschlägt und funktioniert ohne Katzenmissbrauch.


Linux
  1. Bash-Scripting(I)

  2. Bash sortieren

  3. Bash-Exportbefehl

  4. Führen Sie den Bash-Befehl auf der Jenkins-Pipeline aus

  5. Wie schlafe ich für eine Millisekunde in bash oder ksh

Linux-Sleep-Befehl (Pausieren eines Bash-Skripts)

Bash if..else-Anweisung

Bash-Arrays

Bash Shebang

Bash-printf-Befehl

Assoziatives Array in Bash