GNU/Linux >> Linux Esercitazione >  >> Linux

Fai uscire Tail -f su un tubo rotto?

Voglio guardare un file finché non appare un po' di testo

Ho trovato questa risposta:`tail -f` fino a quando non viene visualizzato il testo

ma quando l'ho provato su Ubuntu, non esce:

$ echo one > test.txt
$ echo two >> test.txt
$ echo three >> test.txt
$ echo four >> test.txt
$ cat test.txt | sed '/w/ q'
one
two
$

funziona come previsto. tuttavia quando provo a pedinare il file

$ tail -f test.txt | sed '/w/ q'
one
two

non esce mai. la coda non si ferma anche se il tubo è rotto.

Qualcuno sa come creare tail esci quando sed esce?

Risposta accettata:

Sono le stesse cose di:

  • Come uscire presto alla chiusura del tubo?
  • Grep lento per uscire dopo aver trovato una corrispondenza?
  • limita l'output di ricerca E evita il segnale 13

In:

cmd1 | cmd2

La tua shell aspetta fino a cmd1 termina anche dopo cmd2 è già terminato. Non è il caso di tutte le conchiglie. Alcuni come la shell Bourne o Korn, per esempio, non lo fanno.

Quando cmd2 dies, la pipe su cmd1 Lo stdout di 's diventa rotto , ma ciò non termina cmd1 all'istante.

cmd1 terminerà la prossima volta che proverà a scrivere su quella pipe. Riceverà quindi un SIGPIPE la cui azione predefinita è terminare il processo.

Con cmd1 ==tail -f file e cmd2 ==sed /w/q , tail -f leggerà le ultime 10 righe del file e le scriverà su stdout (la pipe), in genere in un blocco a meno che le righe non siano davvero grandi e stia lì ad aspettare che venga aggiunto più testo a file .

sed , che viene eseguito contemporaneamente, attenderà l'input sul suo stdin, lo leggerà, lo elaborerà riga per riga e chiuderà se c'è una riga che contiene w .

Non appena (o eventualmente con un ritardo di una riga con alcuni sed implementazione) quando trova quella riga, esce, ma in quel momento, tail ha già scritto nella pipe tutto ciò che aveva per SCRIVERE, quindi non riceverà un SIGPIPE a meno che non venga aggiunto del testo aggiuntivo in seguito al file (a quel punto eseguirà il fatale write() ).

Se vuoi cmd1 per terminare non appena cmd2 termina, avresti bisogno di qualcosa per ucciderlo una volta cmd2 termina. Come con:

sh -c 'echo "$$"; exec tail -f test.txt' | {
  IFS= read pid
  sed /w/q
  kill -s PIPE "$pid"
}

O con bash :

{ sed /w/q; kill -s PIPE "$!"; } < <(exec tail -f text.txt)
  

Modifica 2020

Come notato da @user414777, dalla versione 8.28, l'implementazione GNU di tail , nelle modalità segui, ora non solo esegue il polling dei nuovi dati nei file che monitora, ma controlla anche se il suo stdout diventa una pipe rotta ed esce immediatamente (o entro un secondo se inotify non viene utilizzato), rendendo superflui i lavori sopra descritti.

Correlati:come utilizzare il codice dello stato di uscita?

Tuttavia, nota che solo GNU tail esegue questo tipo di elaborazione, non qualsiasi altra implementazione di tail (AFAIK), e non qualsiasi altra utilità (nemmeno le implementazioni GNU).

Quindi, mentre:

tail -f file | head -n1

Uscirà dopo una riga,

tail -f file | tr '[:lower:]' '[:upper:]' | head -n1

per esempio non sarà necessariamente come tr non controllerà se il suo stdout diventa un tubo rotto, quindi morirà solo se scrive qualcosa lì dopo che la pipe si è rotta come al solito (ed è solo a quel punto che GNU tail -f uscirà).


Linux
  1. Grep e coda -f?

  2. Perché Rsync non riesce con tubo rotto (32), errore nella presa Io (codice 10) su Io.c(820)??

  3. Come uscire da un container Docker

  4. Come uscire se un comando fallisce?

  5. Come ottenere lo stato di uscita di un comando shell utilizzato in GNU Makefile?

Comando coda di Linux

Tubo da B a D? – A&&B || C | D?

Correzione dell'errore del tubo rotto con la connessione SSH

Makefile per non fare nulla

Da VMware e Fedora 29 ssh alla macchina remota causa Broken pipe

Posso far uscire Qemu con errore in caso di kernel panic?