← Весь справочник

head и tail

Первые и последние строки файла, срезы по номерам и слежение за растущим логом через tail -f

head печатает начало файла, tail — конец. По умолчанию — 10 строк. tail -f не завершается, а продолжает выводить новые строки по мере того, как они дописываются в файл, — так смотрят логи в реальном времени.

Синтаксис

head [-n N] [файл…]
tail [-n N] [файл…]
tail -f | -F [-n N] файл…

Без файлов (или с файлом -) обе команды читают stdin.

Опции head

ОпцияЧто делает
-n 5 (-5)первые 5 строк
-n -5всё, кроме последних 5 строк
-c 100первые 100 байт; -c -100 — всё, кроме последних 100 байт
-qне печатать заголовки ==> файл <== при нескольких файлах
-vпечатать заголовок, даже если файл один
-zстроки разделены нулевым байтом, а не \n

Опции tail

ОпцияЧто делает
-n 5 (-5)последние 5 строк
-n +5всё, начиная с 5-й строки (пропустить первые 4)
-c 100 / -c +100последние 100 байт / всё, начиная со 100-го байта
-q / -vне печатать / всегда печатать заголовки файлов
-zстроки разделены нулевым байтом

Числа в -n и -c принимают суффиксы: K = 1024, M = 1024², kB = 1000 и т. д. (head -c 1K).

Слежение за файлом

ОпцияЧто делает
-fпосле вывода не завершаться, а печатать новые строки по мере дописывания. Следит за открытым файлом (--follow=descriptor)
--follow=nameследить за именем: если файл переименовали или удалили и создали заново, переоткрыть его
--retryпродолжать попытки открыть файл, если его пока нет или он недоступен
-Fто же, что --follow=name --retry — правильный выбор для логов с ротацией
--pid=PIDс -f: завершиться, когда процесс PID закончится
-s Nс -f: проверять файл раз в N секунд (по умолчанию 1; при inotify редко нужно)
--max-unchanged-stats=Nс --follow=name: переоткрывать файл, если размер не менялся N проверок (по умолчанию 5)

При слежении за несколькими файлами tail печатает заголовок ==> файл <== каждый раз, когда переключается на другой файл. Об усечении и замене файла он сообщает в stderr: file truncated, has been replaced; following new file.

Примеры

seq 100 > nums.txt

# первые и последние 3 строки
head -n 3 nums.txt
tail -n 3 nums.txt

# пропустить строку-заголовок (например, у CSV или вывода ps)
tail -n +2 nums.txt | head -n 3
ps aux | tail -n +2 | wc -l

# строки с 20-й по 25-ю
head -n 25 nums.txt | tail -n +20
sed -n '20,25p' nums.txt

# всё, кроме последних 95 строк
head -n -95 nums.txt

# первые 16 байт файла — посмотреть сигнатуру
head -c 16 /bin/ls | od -c

# начало каждого из нескольких файлов, с заголовками и без
head -n 1 /etc/passwd /etc/group
head -q -n 1 /etc/passwd /etc/group

# следить за логом: показать последние 20 строк и ждать новых (Ctrl+C — выход)
tail -n 20 -f app.log

# следить по имени — переживёт ротацию лога и появление файла позже
tail -F app.log

# следить за несколькими логами сразу
tail -F app.log error.log

# следить и фильтровать на лету
tail -F app.log | grep --line-buffered ERROR

# следить ограниченное время
timeout 10 tail -f app.log

# следить, пока работает фоновый процесс, и завершиться вместе с ним
sleep 5 &
tail -f app.log --pid=$!

Подводные камни

  • tail -n +5 — это «начиная с 5-й», а не «последние 5». Знак плюс меняет смысл; у head особый смысл у минуса: head -n -5.
  • tail -f держится за открытый файл. Если лог переименуют при ротации (app.log → app.log.1) и создадут новый, tail -f продолжит читать старый файл и новых строк не увидит. Для логов, которые ротируются, используй tail -F. Если файл просто обрезают (> app.log), GNU tail замечает это и пишет file truncated.
  • tail -f никогда не завершается сам. В скрипте он повиснет; ограничь его через timeout или --pid.
  • Буферизация в конвейере. В tail -f … | grep … | … grep копит вывод в буфер, и строки появляются с задержкой. Помогает grep --line-buffered (у sed — -u, у других программ — stdbuf -oL).
  • Нумерация с единицы. tail -n +1 выводит файл целиком, tail -n +2 пропускает первую строку.
  • Без \n в конце последняя «строка» всё равно считается строкой: printf 'a\nb' | tail -n 1 выведет b (без перевода строки).
  • head в конвейере закрывает канал рано. Команда слева может получить SIGPIPE и завершиться с ошибкой — с set -o pipefail это делает весь конвейер неуспешным.

См. также

sed · grep · wc · logrotate