Dlaczego „tail -f… | tail ”nie daje żadnych wyników?


36

Dlaczego poniższe polecenie nie generuje danych wyjściowych?

$ tail -f /etc/passwd | tail

Po przeczytaniu o buforowaniu próbowałem bezskutecznie:

$ tail -f /etc/passwd | stdbuf -oL tail

Zauważ, że następujące wyniki generują dane wyjściowe:

$ tail /etc/passwd | tail

Czyni to:

$ tail -f /etc/passwd | head

Korzystam z wersji tail 8.21 (GNU coreutils).


17
Jakie są ostatnie 10 cyfr π?
Keith Thompson

Odpowiedzi:


15

Myślałem, że widziałem wszystko w systemie UNIX. To pytanie wyrwało mnie z zadowolenia z siebie. Cóż za świetne pytanie!

tailpokazuje ostatnie X linii. tail -frobi to samo, ale zasadniczo w nieskończonej pętli: podczas uruchamiania pokaż ostatnie X linii pliku, a następnie używając magii systemu operacyjnego (np. inotify), monitoruj i pokaż nowe linie.

Aby wykonać swoje zadanie, tailmusi być w stanie zlokalizować koniec pliku. Jeśli tailnie można znaleźć końca pliku, nie może wyświetlić ostatnich X linii, ponieważ „ostatni” jest niezdefiniowany. Co więc robi tailw tym przypadku? Czeka, aż znajdzie koniec pliku.

Rozważ to:

$ chatter() { while :; do date; sleep 1; done; }
$ chatter | tail -f

Wydaje się, że nigdy nie robi to postępu, ponieważ nigdy nie ma określonego końca pliku chatter.

Takie samo zachowanie otrzymasz, jeśli poprosisz tailo podanie ostatnich linii z potoku systemu plików. Rozważać:

$ mkfifo test.pipe
$ tail test.pipe

stdbufobejście postrzeganego problemu było szlachetną próbą. Kluczowym faktem jest jednak to, że buforowanie We / Wy nie jest główną przyczyną: brak określonego końca pliku. Jeśli sprawdzisz kod źródłowy tail.c , zobaczysz file_lineskomentarz funkcji o treści:

END_POS to przesunięcie pliku EOF (jeden większy niż przesunięcie ostatniego bajtu).

i to jest magia. Potrzebujesz końca pliku, aby tail działał w dowolnej konfiguracji. headnie ma tego ograniczenia, potrzebuje tylko początku pliku (którego może nie mieć, spróbuj head test.pipe). Narzędzia zorientowane na strumień, takie jak sedi awknie potrzebują ani początku, ani końca pliku: działają na buforach.


37

tail -fOgon jest właściwie czymś nieznanym w teraźniejszości, więc skąd następny powinien to tailwiedzieć. Z drugiej strony tail -fgłowa jest już znana i można ją było przetworzyć.

Lub, mówiąc prościej: tailodnosi się do końca pliku, ale strumień wyjściowy tail -fnie ma EOF (przynajmniej nie przed zakończeniem).

Jeśli okaże się pierwszy tail„s PID i zabić go, należy następnie zobacz wynik od drugiego.


21

Odpowiedź techniczna

Podczas działania ze strumieniem jako wejściem tailutrzymuje nbufor -line, który wypełnia podczas odczytywania strumienia, ale nie może wyprowadzać tych linii, dopóki nie osiągnie końca strumienia, tj. Otrzymuje specjalny EOFkod podczas próby odczytu z wejścia strumień. Wywołanie tail -fnie kończy się, dlatego nigdy nie zamyka swojego strumienia, co uniemożliwia np. Zwrócenie 10 ostatnich linii tego strumienia.


3

Funkcja tailpolega na wyświetleniu ostatniej części - „ogona” - wejścia lub pliku. (Opcja -fdotyczy tego, co zrobi później, więc nie ma to znaczenia tutaj.)

Pomyślmy o pliku:

Jaka jest ostatnia część pliku ?
Powiedzmy, że to ostatnie n linii pliku.

Kiedy czytamy wiersz ipliku wejściowego, jak zdecydować, czy należy go wydrukować, czy nie?
Nie wiemy, czy jest to ostatnia część - ponieważ nie wiemy, która będzie ostatnia linia. Więc nie możemy teraz go wydrukować.

Musimy zachować linię, dopóki nie stanie się jasne, że jest to część ostatnich nlinii lub nie może już być jej częścią, ponieważ znamy ndalsze linie

Jeśli teraz dojdziemy do końca pliku , wiemy, że ostatnie nlinie, które zachowaliśmy, są w rzeczywistości ostatnimi nliniami pliku.

Teraz w przypadku

tail -f /etc/passwd | tail

pierwszy tailodczytuje plik, a następnie czeka, aby uzyskać z niego więcej danych , aby go również zapisać. Więc nie zasygnalizuje końca pliku drugiemu ogonowi, jeśli chodzi o koniec pliku, który czyta. Bez tego drugi tail nigdy nie zostaje powiadomiony o końcu pliku, więc nigdy nie może dowiedzieć się, jakie są ostatnie wiersze, które powinien wydrukować.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.