ciągły odczyt z nazwanej rury (cat lub tail -f)

16

Skonfigurowałem rsyslogrejestrowanie niektórych zdarzeń dziennika w /dev/xconsole:

*.*;cron.!=info;mail.!=info      |/dev/xconsole

/dev/xconsoleto nazwany potok ( fifo). Jeśli chcę zobaczyć, co jest rejestrowane, mogę to zrobić cat /dev/xconsole. Jestem zaskoczony, widząc, że polecenie cat /dev/xconsolenie kończy się po odczytaniu pliku, ale działa jak tail -f. innymi słowy, oba polecenia zachowują się tak samo:

cat /dev/xconsole
tail -f /dev/xconsole

Czy ktoś może wyjaśnić, dlaczego tak jest?

Czy jest jakaś różnica między nimi?

Martin Vegter
źródło

Odpowiedzi:

18

catkontynuuje czytanie, dopóki nie otrzyma EOF. Rura wytwarza EOF na wyjściu tylko wtedy, gdy otrzymuje EOF na wejściu. Demon rejestrujący otwiera plik, zapisuje do niego i utrzymuje go otwarty - podobnie jak w przypadku zwykłego pliku - aby EOF nigdy nie był generowany na wyjściu. catpo prostu kontynuuje czytanie, blokując za każdym razem, gdy wyczerpuje to, co aktualnie znajduje się w potoku.

Możesz to wypróbować ręcznie:

$ mkfifo test
$ cat test

I w innym terminalu:

$ cat > test
hello

Wyjdzie na drugim terminalu. Następnie:

world

Na drugim terminalu będzie więcej danych wyjściowych. Jeśli teraz Ctrl-D wejście, to drugie catrównież się zakończy.

W takim przypadku jedyną zauważalną różnicą między cati tail -fbędzie, jeśli demon rejestrujący zostanie zakończony lub zrestartowany: catzatrzyma się na stałe, gdy koniec zapisu potoku zostanie zamknięty, ale tail -fbędzie kontynuował (ponownie otwierał plik), gdy demon zostanie zrestartowany.

Michael Homer
źródło
przepraszam, nie widzę skąd wziąłby się „świat” w twoim przykładzie :)
Alexander Mills
Po wpisaniu.
Michael Homer,
1
A potem piszesz world, a oto „świat” pojawia się w drugim terminalu.
Michael Homer,
2

Istnieje również różnica w buforowaniu między cati tail -f. Możesz to sprawdzić:

Utwórz potok: mkfifo pipe

Rozpocznij czytanie potoku, używając catw tle:cat pipe &

Otwórz potok i pisz do niego co sekundę: perl -MFcntl -we 'sysopen(my $fh, "pipe", O_WRONLY | O_NONBLOCK); while() {warn "written: " . syswrite($fh, "hello\n"); sleep 1}'

Teraz spróbuj tego z tail -f pipe &zamiast cat. Możesz więc zobaczyć, że catdrukuje linie, jak tylko zostaną zapisane do potoku za pomocą skryptu perl, a tail -f buforuje je do 4 KB przed drukowaniem na standardowe wyjście.

Zainteresowany
źródło