непрерывное чтение из именованного канала (cat или tail -f)

16

Я настроил rsyslogзапись определенных событий журнала в /dev/xconsole:

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

/dev/xconsoleявляется именованным каналом ( fifo). Если я хочу увидеть, что регистрируется, я могу сделать cat /dev/xconsole. Я удивлен, увидев, что команда cat /dev/xconsoleне завершает чтение файла, а действует как tail -f. другими словами, две команды ведут себя одинаково:

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

Может кто-нибудь объяснить, почему это так?

Есть ли разница между ними?

Мартин Вегтер
источник

Ответы:

18

catпродолжает читать, пока не получит EOF. Труба производит EOF на выходе, только когда она получает EOF на входе. Демон регистрации открывает файл, записывает в него и сохраняет его открытым, как это делается для обычного файла, поэтому EOF никогда не генерируется на выходе. catпросто продолжает читать, блокируя всякий раз, когда исчерпывает то, что в данный момент находится в канале.

Вы можете попробовать это сами:

$ mkfifo test
$ cat test

И в другом терминале:

$ cat > test
hello

Там будет вывод на другой терминал. Потом:

world

Там будет больше вывода в другом терминале. Если вы сейчас нажмете Ctrl-D на вводе, другой catтоже прекратит работу.

В этом случае единственное наблюдаемое различие между catи tail -fбудет, если демон ведения журнала будет завершен или перезапущен: catостановится навсегда, когда конец записи канала закрыт, но tail -fпродолжит работу (повторное открытие файла) при перезапуске демона.

Майкл Гомер
источник
извините, я не вижу, откуда взялся "мир" в вашем примере :)
Александр Миллс
От того, как ты его напечатал.
Майкл Гомер
1
И тогда вы печатаете world, и вот, "мир" появляется в другом терминале.
Майкл Homer
2

Существует также разница в буферизации между catи tail -f. Вы можете проверить это:

Создать трубу: mkfifo pipe

Начните читать канал, используя catв фоновом режиме:cat pipe &

Откройте трубу и пишите ей каждую секунду: perl -MFcntl -we 'sysopen(my $fh, "pipe", O_WRONLY | O_NONBLOCK); while() {warn "written: " . syswrite($fh, "hello\n"); sleep 1}'

Теперь попробуйте это tail -f pipe &вместо cat. Таким образом, вы можете видеть, что catстроки печатаются сразу после их записи в конвейер с помощью perl-скрипта, в то время как они tail -f буферизуют до 4 КБ перед печатью на стандартный вывод.

Увлекающийся
источник
-2

catпоказывает весь файл, когда tail -fпоказывает только последние строки и следует. Поэтому, если файл короткий, они ведут себя одинаково, но если файл большой (более 100 строк), вы можете увидеть четкую разницу между ними двумя.

Дополнительная информация об этих командах:

tail http://www.computerhope.com/unix/utail.htm

cat http://www.computerhope.com/unix/ucat.htm

DNS1
источник