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á.
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).