GNU/Linux >> Znalost Linux >  >> Linux

Nechat Tail -f vyjet na prasklé potrubí?

Chci sledovat soubor, dokud se neobjeví kousek textu

Našel jsem tuto odpověď:`tail -f` dokud se nezobrazí text

ale když jsem to zkusil na ubuntu, neukončí se:

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

funguje podle očekávání. ale když se pokusím ocasit soubor

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

nikdy nevyjde. ocas se nezastaví, i když je potrubí zlomené.

Ví někdo, jak udělat tail ukončete, když sed odchody?

Přijatá odpověď:

Jsou to stejné věci jako v:

  • Jak předčasně ukončit po uzavření potrubí?
  • Po nalezení shody se ukončuje pomalu?
  • omezit výstup hledání A vyhnout se signálu 13

V:

cmd1 | cmd2

Váš shell náhodou počká, dokud cmd1 skončí i po cmd2 již byla ukončena. To není případ všech skořápek. Některé jako Bourne nebo Korn shell například ne.

Když cmd2 dies, potrubí na cmd1 's stdout se rozbije , ale tím se cmd1 neukončí okamžitě.

cmd1 se ukončí při příštím pokusu o zápis do této roury. Poté obdrží SIGPIPE, jehož výchozí akcí je ukončení procesu.

Pomocí cmd1 ==tail -f file a cmd2 ==sed /w/q , tail -f přečte posledních 10 řádků souboru a zapíše je do stdout (potrubí), obvykle v jednom bloku, pokud řádky nejsou opravdu velké a budou tam čekat na další text, který bude připojen k file .

sed , který běží souběžně, počká na vstup na svém stdin, přečte jej, zpracuje jej řádek po řádku a ukončí se, pokud existuje řádek, který obsahuje w .

Co nejdříve (nebo možná s jednořádkovým zpožděním s nějakým sed implementace), jakmile najde tento řádek, opustí se, ale v tu chvíli tail již zapsal do roury vše, co měl k ZÁPISU, takže neobdrží SIGPIPE, pokud není do souboru později přidán nějaký další text (v tomto okamžiku provede fatální write() ).

Pokud jste chtěli cmd1 ukončit, jakmile cmd2 skončí, budete potřebovat něco, co by ho jednou zabilo cmd2 končí. Jako s:

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

Nebo pomocí bash :

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

Úprava 2020

Jak poznamenal @user414777, od verze 8.28 je GNU implementace tail , v režimech sledování se nyní nejen dotazuje na nová data v souboru (souborech), který monitoruje, ale také kontroluje, zda se jeho stdout nestane rozbitým potrubím a okamžitě se opustí (nebo během jedné sekundy, pokud inotify se nepoužívá), takže výše uvedená obcházení není zbytečná.

Související:Jak používat kód stavu ukončení?

Pamatujte však, že pouze GNU tail provádí tento druh zpracování, nikoli jakákoli jiná implementace tail (AFAIK) a ne žádný jiný nástroj (ani implementace GNU).

Takže zatímco:

tail -f file | head -n1

Ukončí se po jednom řádku,

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

například nebude nutně jako tr nebude sledovat, zda se z jeho stdout nestane prasklá trubka, a tak zemře pouze v případě, že napíše něco tam poté, co prasklo potrubí jako obvykle (a teprve v tomto bodě GNU tail -f ukončí se).


Linux
  1. Nepřetržité čtení z pojmenované dýmky (kočka nebo ocas -f)?

  2. Jak vytvořit obousměrné potrubí mezi dvěma programy?

  3. Proč Rsync selže s rozbitým potrubím (32), chyba v zásuvce Io (kód 10) na Io.c (820)?

  1. Jak opustit kontejner Docker

  2. Jak ukončit, pokud příkaz selhal?

  3. Potrubí „najít“ na „ocas“.

  1. Grep And Tail -f?

  2. Makefile, aby nic nedělal

  3. Mohu Qemu ukončit se selháním při panice jádra?