Learning Platform
Глоссарий Troubleshooting
Урок 06.03 · 20 мин
Начальный
catlessheadtailtail -fLogs

Чтение файлов: cat, less, head, tail

Junior DE 30% времени читает файлы: логи, CSV, конфиги, JSON, error-сообщения. Для каждой задачи есть свой инструмент: cat для маленьких, less для больших, head/tail для частичного, tail -f для live-просмотра растущих логов. В этом уроке — каждый с реальными сценариями.


cat: вывести содержимое

cat (concatenate) — самая простая команда. Выводит содержимое файла в stdout.

$ cat /etc/hostname
my-server

$ cat ~/.bashrc | head -10
# ~/.bashrc: executed by bash(1) for non-login shells.
...

cat подходит для:

  • Маленьких файлов (до пары MB).
  • Когда нужно подать в pipeline (cat file | grep ...).
  • Конкатенации нескольких файлов: cat file1 file2 > combined.

cat НЕ подходит для:

  • Больших файлов — вы потеряете контроль, и терминал зальёт миллионом строк.
  • Бинарных файлов — мусор на экране, иногда ломает терминал.
# Несколько файлов
$ cat file1.txt file2.txt
# Содержимое file1, потом file2

# С номерами строк
$ cat -n /etc/hostname
     1  my-server

# Показывать невидимые символы (Tab, CR)
$ cat -A file.txt
Hello World$         # $ — это \n
This^Iis^Itab$       # ^I — это Tab

cat -A особенно полезен, когда подозреваете, что в файле скрытые символы: лишние пробелы, Windows-line endings (CRLF), tabs.

TIP

«Useless use of cat» — известный антипаттерн: cat file | grep foo. Лучше grep foo file. Cat создаёт лишний процесс и pipe, без пользы. Исключения: (1) когда читаешь несколько файлов разом, (2) когда хочется left-to-right pipeline для читаемости. Подробнее в модуле 9.


bat: cat на стероидах

bat (Rust-замена cat) — это cat с подсветкой синтаксиса, нумерацией строк, paging для длинных файлов.

$ sudo apt install -y bat   # на Debian/Ubuntu пакет иногда называется batcat
$ alias bat=batcat
# или
$ brew install bat

$ bat config.yaml
───────┬────────────────────────────
 File: config.yaml
───────┼────────────────────────────
   1 database:
   2   host: localhost
   3   port: 5432
───────┴────────────────────────────

bat понимает синтаксис 100+ языков и подсвечивает. Для DE особенно полезно: читать Python, YAML, JSON, SQL, Dockerfile с подсветкой.

В скриптах не используйте bat (medium fluffy output). Только для interactive.


less: paged viewer

Для больших файлов — less. Он не загружает файл целиком, читает страницами.

$ less /var/log/syslog
# Открывается paged view

Главные команды внутри less:

Управление в less
↑ / ↓ или j / kСкролл по одной строке (vim-style и стрелки)
PgUp / PgDn или Space / bСкролл по странице (b — back)
g / Gg — в начало файла, G — в конец. Полезно для перехода к свежим логам в конце
/patternПоиск вперёд. После нажатия enter — найдёт первое совпадение. n — следующее, N — предыдущее
?patternПоиск назад
qQuit. Выход из less
FFollow mode (как tail -f). Файл продолжает читаться по мере роста. Ctrl-C — выход из follow в обычный less
-NВключить нумерацию строк (можно `less -N` при запуске или :-N внутри)
-SНе переносить длинные строки. Полезно для CSV — каждая строка не переносится, видна целиком (можно скроллить вбок)
# Просмотр большого CSV
$ less -S big-data.csv
# -S чтобы строки не переносились (CSV-строки длинные)

# Просмотр с подсветкой синтаксиса (если есть source-highlight)
$ less -R colored-output.txt

# Просмотр сжатого файла прямо
$ zless logs.gz
# или
$ less /var/log/syslog.1.gz   # современный less сам разжимает

head: первые N строк

head выводит первые 10 строк (по умолчанию):

$ head /var/log/syslog
May 13 10:00:01 server systemd[1]: Started Daily apt download activities.
May 13 10:00:01 server systemd[1]: Finished Daily apt download activities.
...

С опциями:

$ head -n 5 file.txt        # первые 5 строк
$ head -5 file.txt          # короткая запись, то же самое

$ head -c 1024 file.bin     # первые 1024 байта

head часто используется в pipeline:

$ ls -la | head -5
total 240
drwxr-xr-x  4 user user  4096 May 13 14:00 .
drwxr-xr-x 15 user user  4096 May 13 12:00 ..
-rw-r--r--  1 user user   220 May 13 12:00 .bashrc
drwxr-xr-x  2 user user  4096 May 13 13:00 projects

tail: последние N строк

tail — обратная head, последние 10 строк:

$ tail /var/log/syslog
# Последние 10 строк, обычно — самые свежие события

Опции:

$ tail -n 50 file.log        # последние 50
$ tail -n +5 file.log        # начиная со строки 5 (НЕ последние!)

$ tail -c 1024 file.bin      # последние 1024 байта

Для DE и системного администрирования tail — самая нужная команда. Особенно tail -f.


tail -f: следить за изменениями

tail -f (follow) — это работа Junior DE на 80%. Команда выводит последние строки и продолжает выводить новые по мере появления.

$ tail -f /var/log/syslog
May 13 14:00:01 server cron[1234]: ETL pipeline started
May 13 14:00:02 server cron[1234]: ETL pipeline running
# Курсор моргает — ждёт новых строк
# Каждая новая строка появляется автоматически

Это супер-полезно для:

  • Просмотра логов сервиса в реальном времени.
  • Отладки запуска приложения.
  • Мониторинга, что что-то происходит.
# Логи DAG Airflow в реальном времени
$ tail -f /var/log/airflow/dag_processor.log

# Логи nginx
$ tail -f /var/log/nginx/access.log

# Логи всех файлов в директории (несколько одновременно)
$ tail -f /var/log/*.log
==> /var/log/syslog <==
[последние строки syslog]
==> /var/log/auth.log <==
[последние строки auth.log]

Когда появляется новая строка в любом файле, tail переключает контекст и показывает её. Очень удобно.

Ctrl-C — выход из follow mode.


tail -F vs tail -f

Тут важная разница. Когда файл логов ротируется (например, logrotate переименовывает file.log в file.log.1 и создаёт новый file.log), что происходит?

  • tail -f держит file descriptor открытым на ОРИГИНАЛЬНЫЙ файл. Когда тот переименован — tail продолжает читать ОТ старого имени, новые записи в новом файле НЕ попадают.
  • tail -F (большая F) переоткрывает файл по имени. После rotation tail заметит, что файл с тем именем стал новым, и переключится на него.
# Для production-логов всегда -F
$ tail -F /var/log/airflow/scheduler.log

На macOS BSD-tail только -f, но он автоматически делает то же, что Linux -F (переоткрывает). На Linux GNU-tail чётко разделение -f vs -F.


less +F: альтернатива tail -f

less +F — это less, запущенный в follow mode. Преимущества над tail -f:

  • Можно нажать Ctrl-C для выхода из follow и сразу скроллить назад (стрелками, /search).
  • Меньше шума: длинные строки переносятся аккуратно (или -S для без переноса).
  • Поиск встроен (/pattern).
$ less +F /var/log/syslog
# Tail-mode
[последние строки + ждёт новых]

# Ctrl-C — выход из follow, теперь обычный less
# /ERROR<Enter> — найти ошибку
# n — следующее совпадение
# Shift-F — снова войти в follow mode

Это про-tip: для отладки сервиса (нужно скроллить, искать, потом снова смотреть live) — less +F лучше tail -f. Для просто наблюдения за live — tail -f достаточно.


Связка с pipeline

Анализ IP-трафика — откуда берутся адреса в access.log
# Последние 20 ошибок
$ grep ERROR /var/log/app.log | tail -20

# Топ-10 IP по числу запросов
$ awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10

# Первые 100 строк CSV для понимания структуры
$ head -100 big-data.csv | column -t -s ','
# column превращает в красивые столбцы

# Размер новых записей в реальном времени (грубое подсчёт)
$ tail -f /var/log/syslog | wc -l

Просмотр сжатых файлов

Логи в production часто архивируются:

$ ls /var/log
syslog              # текущий, plain
syslog.1            # вчерашний, plain
syslog.2.gz         # позавчерашний, gzipped
syslog.3.gz
syslog.4.gz

Чтобы читать .gz без разжатия:

# zcat — cat для gzip
$ zcat /var/log/syslog.2.gz | tail -50

# zless — less для gzip
$ zless /var/log/syslog.2.gz

# zgrep — grep для gzip
$ zgrep ERROR /var/log/syslog.2.gz

Аналогично есть bzcat/bzless/bzgrep для .bz2, xzcat/xzless/xzgrep для .xz, zstdcat для .zst.

# Все варианты в одной команде:
$ zgrep -h ERROR /var/log/syslog*  # старые .gz и текущий plain

Подробнее про сжатие — в модуле 13.


Просмотр JSON и структурных данных

Для DE-данных хорошие инструменты:

# JSON с подсветкой и форматированием
$ cat data.json | jq .
# или
$ jq . data.json

# JSON одной строкой (compact)
$ jq -c . data.json

# Конкретное поле
$ jq '.data[0].name' data.json

# CSV — нормальная табличная визуализация
$ cat data.csv | column -t -s,
$ csvlook data.csv          # требует csvkit
$ visidata data.csv         # интерактивный TUI

Подробнее про jq и работу с CSV — в модуле 19.


Попробуй сам

$ mkdir -p ~/linux-sandbox/lesson-read
$ cd ~/linux-sandbox/lesson-read

# Создаём большой файл с номерами строк
$ seq 1 1000 > big.txt
$ wc -l big.txt
1000 big.txt

# Базовое
$ cat big.txt | head
1
2
3
...
10

$ tail big.txt
991
992
...
1000

# С N строк
$ head -5 big.txt
1
2
3
4
5

$ tail -3 big.txt
998
999
1000

# Less для просмотра
$ less big.txt
# Внутри: G (в конец), g (в начало), /500<Enter> (найти 500), q (выход)

# Симуляция tail -f
# В одном терминале:
$ tail -f big.txt

# В другом терминале:
$ echo "new line $(date)" >> big.txt
# Сразу появится в tail -f первого терминала

Реальный сценарий — следить за логом:

# Если есть Postgres:
$ sudo tail -F /var/log/postgresql/postgresql-17-main.log

# Или syslog
$ sudo tail -F /var/log/syslog

Проверка знанийKnowledge check
Junior следит за логом сервиса `tail -f /var/log/app.log`, но через 4 часа замечает: новых записей нет, хотя сервис активно работает. Что произошло?
ОтветAnswer
Скорее всего, лог-файл был отротирован (logrotate переименовал /var/log/app.log в /var/log/app.log.1 и создал новый пустой /var/log/app.log для дальнейших записей). `tail -f` держит file descriptor открытым на ИЗНАЧАЛЬНЫЙ файл (теперь app.log.1) — этот файл больше не растёт, потому что сервис пишет в новый app.log. Поэтому tail тихо 'висит'. Решение: использовать `tail -F` (большая F), которая переоткрывает файл по имени. Когда rotation происходит, -F замечает, что файл с этим именем стал новым, и переключается. На современных Linux-системах с journald (systemd) альтернатива — `journalctl -u app -f` (follow), которая не зависит от файловых rotation и работает с структурированными логами через systemd. Для production-DE привычка: `tail -F` для файлов, `journalctl -fu service` для systemd-сервисов. Подробнее про journalctl — в модуле 15.

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 5. Когда использовать less вместо cat?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5