Какие параметры есть у команды tail
Что проверяют
У Python-разработчика это вопрос про работу с логами на сервере: умеете ли вы посмотреть конец файла и следить за ним, не открывая гигабайтный лог целиком. Следом часто спрашивают, чем -f отличается от -F и как написать аналог tail на Python.
Как отвечать
Основные ключи GNU tail:
-n N: последние N строк, по умолчанию 10. Вариант-n +Nвыводит всё начиная со строки N, удобно, чтобы отрезать заголовок CSV;-c N: последние N байт;-f: следить за файлом и печатать новые строки по мере записи;-F: то же, что--follow=name --retry. Следит за именем, а не за открытым дескриптором, поэтому переживает ротацию логов;--pid=PID: вместе с-fзавершиться, когда процесс с этим PID умрёт;-s N: интервал опроса при слежении;-qи-v: убрать или всегда показывать заголовки==> имя <==при нескольких файлах.
Типичные связки: tail -n 100 -F app.log для старта с контекстом, tail -F app.log | grep ERROR. В контейнере аналог docker logs -f --tail 100, для сервиса systemd journalctl -u app -f.
Для Python важна обратная сторона. Если приложение пишет через print в перенаправленный stdout, интерпретатор буферизует вывод блоками, и в tail -f строки приходят пачками. Помогают PYTHONUNBUFFERED=1, print(..., flush=True) или logging, чей StreamHandler сбрасывает буфер после каждой записи. Аналог tail -n на Python пишется через collections.deque(f, maxlen=n), а для больших файлов через seek от конца.
Где спотыкаются
Используют -f на логе, который ротируется. После переименования файла tail продолжает читать старый дескриптор и молчит, нужен -F.
Неверно объясняют --max-unchanged-stats. Он не завершает tail, а задаёт, через сколько проверок без изменения размера tail в режиме --follow=name переоткроет файл, чтобы заметить подмену.
Строят цепочку tail -f | grep | awk и ждут вывода. Средняя команда буферизует вывод в пайп, и без grep --line-buffered строки приходят большими порциями.