Чому «хвіст -f… | хвіст »не вдалося дати жодного результату?


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).


17
Які останні 10 цифр π?
Кіт Томпсон

Відповіді:


15

Я думав, що бачив усе в UNIX. Це питання позбавило мене від саморобності. Яке чудове запитання!

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

Щоб виконати свою роботу, 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 (на один більший за зміщення останнього байта).

і це магія. Щоб хвіст працював у будь-якій конфігурації, вам потрібен кінець файлу. headне має цього обмеження, воно просто потребує запуску файлу (якого він може не мати, спробуйте head test.pipe). Стрім орієнтовані інструменти , як sedі awkпотреби ні на початку або в кінці файлу: вони працюють на буферах.


37

tail -fХвіст насправді є щось невідоме в сьогоденні, так як наступні повинні це tailзнати. З іншого боку tail -f, голова - це щось вже відоме і воно може бути оброблене.

Або простіше кажучи: tailвідносно кінця файлу, але вихідний потік не tail -fотримав EOF (принаймні, не до його закінчення).

Якщо ви знайшли перший tailідентифікатор процесу «s і вбити його, ви повинні потім побачити вихід з другого.


21

Технічна відповідь

Запускаючи потік як вхідний, tailзберігає nбуфер -line, який він заповнює, коли він читає потік, але він не може вивести ці рядки, поки не досягне кінця потоку, тобто він отримає спеціальний EOFкод при спробі зчитування з входу потік. Викликання tail -fне закривається, тому він ніколи не закриє його потік, що унеможливлює, наприклад, повернення 10 останніх рядків цього потоку.


3

Функція tailполягає в тому, щоб показати останню частину - "хвіст" - вводу або файлу. (Варіант -fполягає в тому, що робити пізніше, так що це не актуально.)

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

Яка остання частина файлу ?
Скажімо, це останні n рядків файлу.

Коли ми читаємо рядок iвхідного файлу, як вирішити, чи потрібно його друкувати чи ні?
Ми не знаємо, чи є це в останній частині - тому що ми не знаємо, який буде останній рядок. Тож ми не можемо її друкувати зараз.

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

Якщо ми зараз підійдемо до кінця файлу , ми знаємо, що останні nзбережені рядки насправді є останніми nрядками файлу.

Тепер у випадку з

tail -f /etc/passwd | tail

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.