Чтение файлов: 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.
«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:
# Просмотр большого 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