Почему «хвост-ф ... | хвост »не в состоянии произвести какой-либо вывод?

36

Почему следующая команда не выдает никаких результатов?

$ tail -f /etc/passwd | tail

Прочитав о буферизации , я попробовал следующее безрезультатно:

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

Обратите внимание, что следующее действительно производит вывод:

$ tail /etc/passwd | tail

Так же это:

$ tail -f /etc/passwd | head

Я использую хвостовую версию 8.21 (GNU coreutils).

thomie
источник
17
Каковы последние 10 цифр π?
Кит Томпсон,

Ответы:

15

Я думал, что видел все в UNIX. Этот вопрос ударил меня из самодовольства. Какой замечательный вопрос!

tail показывает последние X строк. tail -fделает то же самое, но по существу в бесконечном цикле: при запуске показывать последние X строк файла, затем использовать магию ОС (например, inotify), отслеживать и показывать новые строки.

Чтобы сделать свою работу, tailдолжен быть в состоянии найти конец файла. Если tailне удается найти конец файла, он не может показать последние X строк, потому что «последний» не определен. Так что жеtail делать в этом случае? Он ждет, пока не найдет конец файла.

Учти это:

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

Похоже, что это никогда не приводит к прогрессу, потому что нет определенного конца файла из chatter .

Вы получите то же самое поведение, если попросите tailуказать последние строки из канала файловой системы. Рассмотреть возможность:

$ mkfifo test.pipe
$ tail test.pipe

stdbufобойти воспринятую проблему было благородной попыткой. Ключевой факт, однако, заключается в том, что буферизация ввода / вывода не является основной причиной: отсутствие определенного конца файла. Если вы посмотрите исходный код tail.c , вы увидите file_linesкомментарий функции:

END_POS - это смещение файла EOF (на единицу больше, чем смещение последнего байта).

и это магия Вам нужен конец файла для tail для работы в любой конфигурации. headне имеет этого ограничения, ему просто нужен запуск файла (чего может не быть, попробуйте head test.pipe). Инструменты, ориентированные на потоки, любят sedи не awkнуждаются ни в начале, ни в конце файла: они работают с буферами.

епископ
источник
37

tail -fХвост на самом деле является чем-то неизвестным в настоящем, так как следующий должен это tailзнать. С другой стороны tail -f, голова уже известна и может быть обработана.

Или, проще говоря: tailотносительно конца файла, но поток вывода не tail -fполучил EOF (по крайней мере, до его завершения).

Если вы нашли первый tailидентификатор процесса «s и убить его, вы должны затем увидеть выход из второго.

Ганима
источник
21

Технический ответ

При работе с потоком в качестве входных данных tailсохраняет nбуфер -линии, который он заполняет при чтении потока, но он не может выводить эти строки, пока не достигнет конца потока, т.е. он получает специальный EOFкод при попытке чтения из ввода ручей. Вызов tail -fне завершается, поэтому он никогда не закроет свой поток, что делает невозможным, например, возврат 10 последних строк этого потока.

sleblanc
источник
3

Функция tailсостоит в том, чтобы показать последнюю часть - «хвост» - ввода или файла. (Опция -fо том, что он делает позже, так что здесь это не имеет значения.)

Давайте подумаем о файле:

Какая последняя часть файла ?
Допустим, это последние n строк файла.

Когда мы читаем строку iвходного файла, как решить, должен ли он быть напечатан или нет?
Мы не знаем, есть ли это в последней части - потому что мы не знаем, какой будет последняя строка. Поэтому мы не можем распечатать его сейчас.

Нам нужно сохранять строку, пока не станет ясно, что она является частью последних nстрок или больше не может быть ее частью, потому что мы знаем nдальнейшие строки

Если мы теперь дошли до конца файла , мы знаем, что последние nсохраненные строки на самом деле являются последними nстроками файла.

Теперь, в случае

tail -f /etc/passwd | tail

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

Volker Siegel
источник