Почему следующая команда не выдает никаких результатов?
$ 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).
Ответы:
Я думал, что видел все в UNIX. Этот вопрос ударил меня из самодовольства. Какой замечательный вопрос!
tail
показывает последние X строк.tail -f
делает то же самое, но по существу в бесконечном цикле: при запуске показывать последние X строк файла, затем использовать магию ОС (например, inotify), отслеживать и показывать новые строки.Чтобы сделать свою работу,
tail
должен быть в состоянии найти конец файла. Еслиtail
не удается найти конец файла, он не может показать последние X строк, потому что «последний» не определен. Так что жеtail
делать в этом случае? Он ждет, пока не найдет конец файла.Учти это:
Похоже, что это никогда не приводит к прогрессу, потому что нет определенного конца файла из
chatter
.Вы получите то же самое поведение, если попросите
tail
указать последние строки из канала файловой системы. Рассмотреть возможность:stdbuf
обойти воспринятую проблему было благородной попыткой. Ключевой факт, однако, заключается в том, что буферизация ввода / вывода не является основной причиной: отсутствие определенного конца файла. Если вы посмотрите исходный код tail.c , вы увидитеfile_lines
комментарий функции:и это магия Вам нужен конец файла для tail для работы в любой конфигурации.
head
не имеет этого ограничения, ему просто нужен запуск файла (чего может не быть, попробуйтеhead test.pipe
). Инструменты, ориентированные на потоки, любятsed
и неawk
нуждаются ни в начале, ни в конце файла: они работают с буферами.источник
tail -f
Хвост на самом деле является чем-то неизвестным в настоящем, так как следующий должен этоtail
знать. С другой стороныtail -f
, голова уже известна и может быть обработана.Или, проще говоря:
tail
относительно конца файла, но поток вывода неtail -f
получил EOF (по крайней мере, до его завершения).Если вы нашли первый
tail
идентификатор процесса «s и убить его, вы должны затем увидеть выход из второго.источник
Технический ответ
При работе с потоком в качестве входных данных
tail
сохраняетn
буфер -линии, который он заполняет при чтении потока, но он не может выводить эти строки, пока не достигнет конца потока, т.е. он получает специальныйEOF
код при попытке чтения из ввода ручей. Вызовtail -f
не завершается, поэтому он никогда не закроет свой поток, что делает невозможным, например, возврат 10 последних строк этого потока.источник
Функция
tail
состоит в том, чтобы показать последнюю часть - «хвост» - ввода или файла. (Опция-f
о том, что он делает позже, так что здесь это не имеет значения.)Давайте подумаем о файле:
Какая последняя часть файла ?
Допустим, это последние n строк файла.
Когда мы читаем строку
i
входного файла, как решить, должен ли он быть напечатан или нет?Мы не знаем, есть ли это в последней части - потому что мы не знаем, какой будет последняя строка. Поэтому мы не можем распечатать его сейчас.
Нам нужно сохранять строку, пока не станет ясно, что она является частью последних
n
строк или больше не может быть ее частью, потому что мы знаемn
дальнейшие строкиЕсли мы теперь дошли до конца файла , мы знаем, что последние
n
сохраненные строки на самом деле являются последнимиn
строками файла.Теперь, в случае
первый
tail
читает файл, а затем ждет, чтобы получить от него больше данных и записать его. Таким образом, он не будет сигнализировать конец файла второму хвосту, когда дело доходит до конца файла, который он читает. Без этого второйtail
никогда не получит уведомление о конце файла, поэтому он никогда не сможет узнать, какие последние строки он должен напечатать.источник