GNU/Linux >> Linux Esercitazione >  >> Linux

Bash:sonno infinito (blocco infinito)

tail non si blocca

Come sempre:per ogni cosa c'è una risposta breve, facile da capire, facile da seguire e completamente sbagliata. Qui tail -f /dev/null rientra in questa categoria;)

Se lo guardi con strace tail -f /dev/null noterai che questa soluzione è tutt'altro che bloccante! Probabilmente è anche peggio del sleep soluzione nella domanda, poiché utilizza (sotto Linux) risorse preziose come inotify sistema. Anche altri processi che scrivono in /dev/null crea tail ciclo continuo. (Sul mio Ubuntu64 16.10 questo aggiunge diverse 10 chiamate di sistema al secondo su un sistema già occupato.)

La domanda era per un comando di blocco

Sfortunatamente, non esiste una cosa del genere ..

Leggi:non conosco alcun modo per archiviarlo direttamente con la shell.

Tutto (anche sleep infinity ) può essere interrotto da qualche segnale. Quindi, se vuoi essere veramente sicuro che non ritorni eccezionalmente, deve essere eseguito in un ciclo, come hai già fatto per il tuo sleep . Si prega di notare che (su Linux) /bin/sleep apparentemente è limitato a 24 giorni (dai un'occhiata a strace sleep infinity ), quindi il meglio che puoi fare probabilmente è:

while :; do sleep 2073600; done

(Nota che credo sleep si ripete internamente per valori superiori a 24 giorni, ma ciò significa:non si blocca, si ripete molto lentamente. Allora perché non spostare questo loop all'esterno?)

.. ma puoi avvicinarti abbastanza con un fifo senza nome

Puoi creare qualcosa che blocchi davvero fintanto che non ci sono segnali inviati al processo. Seguire usa bash 4 , 2 PID e 1 fifo :

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

Puoi controllare che questo si blocchi davvero con strace se ti piace:

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

Come è stato costruito

read blocca se non ci sono dati di input (vedi alcune altre risposte). Tuttavia, il tty (ovvero stdin ) di solito non è una buona fonte, poiché viene chiuso quando l'utente si disconnette. Inoltre potrebbe rubare qualche input dal tty . Non carino.

Per fare read block, dobbiamo aspettare qualcosa come un fifo che non restituirà mai nulla. In bash 4 c'è un comando che può fornirci esattamente un tale fifo :coproc . Se aspettiamo anche il blocco read (che è il nostro coproc ), abbiamo chiuso. Purtroppo questo deve mantenere aperti due PID e un fifo .

Variante con nome fifo

Se non ti preoccupi di usare un nome fifo , puoi farlo come segue:

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

Non usare un loop durante la lettura è un po' approssimativo, ma puoi riutilizzare questo fifo tutte le volte che vuoi e fai il read s termina usando touch "$HOME/.pause.fifo" (se c'è più di una singola lettura in attesa, tutte vengono terminate in una volta).

Oppure usa Linux pause() chiamata di sistema

Per il blocco infinito c'è una chiamata al kernel Linux, chiamata pause() , che fa quello che vogliamo:Aspetta per sempre (fino all'arrivo di un segnale). Tuttavia non esiste (ancora) un programma in spazio utente per questo.

C

Creare un tale programma è facile. Ecco uno snippet per creare un programma Linux molto piccolo chiamato pause che si ferma indefinitamente (richiede diet , gcc ecc.):

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

python

Se non vuoi compilare qualcosa da solo, ma hai python installato, puoi usarlo sotto Linux:

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

(Nota:usa exec python -c ... per sostituire la shell corrente, questo libera un PID. La soluzione può essere migliorata anche con alcuni reindirizzamenti IO, liberando FD inutilizzati. Dipende da te.)

Come funziona (credo):ctypes.CDLL(None) carica la libreria C standard ed esegue il pause() funzione in esso all'interno di un ciclo aggiuntivo. Meno efficiente della versione C, ma funziona.

Il mio consiglio per te:

Rimani al sonno in loop. È facile da capire, molto portatile e blocca la maggior parte del tempo.


sleep infinity fa esattamente quello che suggerisce e funziona senza abusi sui gatti.


Linux
  1. Script Bash(I)

  2. Utilizzo del comando di sospensione di Linux negli script Bash

  3. Ordinamento in bash

  4. comando di esportazione bash

  5. Come eseguo più comandi in background in bash in una singola riga?

Comando di sospensione di Linux (pausa di uno script Bash)

Bash if..else Statement

Matrici Bash

Bash Shebang

Comando Bash printf

Matrice associativa in Bash