Myślałem, że widziałem wszystko w systemie UNIX. To pytanie wyrwało mnie z zadowolenia z siebie. Cóż za świetne pytanie!
tail
pokazuje ostatnie X linii. tail -f
robi 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, tail
musi być w stanie zlokalizować koniec pliku. Jeśli tail
nie można znaleźć końca pliku, nie może wyświetlić ostatnich X linii, ponieważ „ostatni” jest niezdefiniowany. Co więc robi tail
w 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 tail
o podanie ostatnich linii z potoku systemu plików. Rozważać:
$ mkfifo test.pipe
$ tail test.pipe
stdbuf
obejś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_lines
komentarz 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. head
nie 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 sed
i awk
nie potrzebują ani początku, ani końca pliku: działają na buforach.