open atlas
↑ К треку
Командная строка CLI · 10 · 01

Конвейер анализа логов

Собери find, grep, cut, sort, uniq -c и awk в многоступенчатый конвейер, извлекающий реальные данные из access-логов — топ клиентских IP, распределение кодов ответа и всплески ошибок — единственной командой в оболочке.

CLI Senior ◷ 30 min
Уровень
ОсновыJuniorMiddleSenior

Сервер генерирует гигабайты логов Nginx. Что-то вызвало всплеск P99-задержки в 03:47 этим утром. Нужен ответ за две минуты, а не за два часа написания Python. Все необходимые инструменты — find, grep, cut, sort, uniq -c, awk — уже на машине и чисто соединяются через конвейеры. Этот урок строит такой конвейер поэтапно: одна стадия за раз, чтобы понять, что вносит каждая из них, и адаптировать под любой формат логов в продакшне.

Цель

После этого урока ты сможешь собрать инкрементальный конвейер анализа логов с помощью find | xargs grep, cut, sort | uniq -c | sort -rn и awk для извлечения топ клиентских IP, подсчёта кодов ответа и частоты ошибок из стандартных access-логов в формате Combined Log Format.

1

Начни с find для поиска файлов логов среди ротированных архивов. На продакшн-сервере обычно есть access.log, access.log.1, access.log.2.gz и так далее. find находит все; xargs передаёт их как аргументы следующей команде, а не перенаправляет содержимое — это важно, потому что некоторые команды (например, grep -h) нуждаются в именах файлов, а не в stdin.

find /var/log/nginx -name 'access.log*' -not -name '*.gz'

Вывод: список совпавших путей, разделённых переводом строки.

Добавь -mtime -1 для ограничения файлами, изменёнными за последние 24 часа — важно, когда логи ротируются ежедневно и нужны только свежие данные.

find /var/log/nginx -name 'access.log*' -not -name '*.gz' -mtime -1

Никогда не передавай вывод find напрямую в cat для длинных списков — используй xargs, чтобы объединить пути в меньшее количество вызовов grep.

2

Добавь grep для фильтрации по временному окну или классу ошибок. Временная метка Combined Log Format выглядит как [21/Jun/2026:03:. Ищи по префиксу часа, чтобы ограничиться периодом всплеска.

find /var/log/nginx -name 'access.log*' -not -name '*.gz' -mtime -1 \
  | xargs grep '21/Jun/2026:03:'

-h подавляет префикс имени файла в выводе grep (чище для последующего разбора):

find /var/log/nginx -name 'access.log*' -not -name '*.gz' -mtime -1 \
  | xargs grep -h '21/Jun/2026:03:'

Теперь на stdout каждый запрос, залогированный в этот час — потенциально миллионы строк, но все релевантные.

3

Извлеки поле кода статуса с помощью cut. Строка Combined Log Format выглядит так:

192.0.2.1 - alice [21/Jun/2026:03:47:12 +0000] "GET /api/users HTTP/1.1" 200 1234

Поля разделены пробелами. Код статуса — поле 9. cut -d' ' -f9 его извлекает.

find /var/log/nginx -name 'access.log*' -not -name '*.gz' -mtime -1 \
  | xargs grep -h '21/Jun/2026:03:' \
  | cut -d' ' -f9

Вывод: столбец кодов статуса — 200, 404, 503, … по одному на строку. Это входные данные для стадии подсчёта.

4

Подсчитай и ранжируй с помощью sort | uniq -c | sort -rn. Эта трёхкомандная последовательность — канонический идиом гистограммы:

  1. sort — группирует одинаковые строки рядом (требование uniq)
  2. uniq -c — сворачивает серии и добавляет перед каждой её счётчик
  3. sort -rn — сортирует по числовому счётчику по убыванию (максимум сначала)
find /var/log/nginx -name 'access.log*' -not -name '*.gz' -mtime -1 \
  | xargs grep -h '21/Jun/2026:03:' \
  | cut -d' ' -f9 \
  | sort | uniq -c | sort -rn

Пример вывода:

   4821 200
    312 503
     87 404
     14 401

Теперь видно: 503-ошибок в этот час было 312 — это и есть сигнал. Весь конвейер работает секунды на миллионах строк.

5

Расширь с помощью awk для многопольного анализа и вычисленных показателей. awk — швейцарский армейский нож для обработки текста по полям. Используй его для вычисления частоты ошибок за один проход или для извлечения клиентского IP (поле 1) с целью анализа топ-«болтунов».

Топ клиентских IP во время всплеска:

find /var/log/nginx -name 'access.log*' -not -name '*.gz' -mtime -1 \
  | xargs grep -h '21/Jun/2026:03:' \
  | awk '{print $1}' \
  | sort | uniq -c | sort -rn \
  | head -10

Частота ошибок в процентах с помощью awk:

find /var/log/nginx -name 'access.log*' -not -name '*.gz' -mtime -1 \
  | xargs grep -h '21/Jun/2026:03:' \
  | awk '$9 >= 500 {err++} {total++} END {printf "5xx rate: %.1f%%\n", err/total*100}'

awk обрабатывает каждую строку за один проход — промежуточная сортировка не нужна. Используй awk, когда нужна арифметика, условия или несколько выходных столбцов. Используй sort | uniq -c, когда нужны ранжированные счётчики.

Разбор примера

Полный анализ инцидента: найти 5 IP, которые генерируют больше всего 503-ошибок в 10-минутном окне.

find /var/log/nginx -name 'access.log*' -not -name '*.gz' -mtime -1 \
  | xargs grep -h '21/Jun/2026:03:4[0-9]:' \
  | awk '$9 == 503 {print $1}' \
  | sort | uniq -c | sort -rn \
  | head -5

Разбор:

  • grep '21/Jun/2026:03:4[0-9]:' — регулярное выражение 4[0-9] совпадает с минутами 40–49 (10-минутное окно).
  • awk '$9 == 503 {print $1}' — оставляет только строки с 503 и выводит клиентский IP (поле 1).
  • sort | uniq -c | sort -rn | head -5 — идиом ранжирования, ограниченный 5 результатами.

Пример вывода:

    142 192.0.2.47
     89 192.0.2.23
     61 192.0.2.105
     44 192.0.2.8
     31 192.0.2.66

Один IP дал 142 из ~329 общих 503-ошибок в этом окне — это застрявший клиент или retry-петля зависимости, долбящая сервис. Источник найден менее чем за 10 секунд.

Почему это работает

На macOS / BSD sort в некоторых старых версиях не принимает -rn как единый флаг — используй sort -r -n явно. awk на macOS — это one-true-awk (BWK awk), а не gawk; большинство идиомов обработки полей работают идентично. Для сжатых ротированных логов (access.log.2.gz) замени xargs grep на zgrep: find /var/log/nginx -name '*.gz' | xargs zgrep -h 'шаблон'.

Частая ошибка

uniq -c требует отсортированного ввода. Если передать прямо в uniq -c без предварительной сортировки, получишь счётчики для каждой последовательной серии — одинаковые значения в разных позициях считаются отдельно. Всегда sort | uniq -c, но не uniq -c в одиночку. Вторая распространённая ошибка: использование sort -n (по возрастанию) без -r, когда нужен максимум сначала — придётся читать вывод с конца.

Проверь себя
Викторина

Ты запускаешь: cat access.log | cut -d' ' -f9 | uniq -c | sort -rn. Вывод выглядит неправильно — счётчики по '1' для каждой строки. Какова наиболее вероятная причина?

Итог

Конвейер анализа логов объединяет шесть инструментов последовательно: find находит файлы логов по всем ротациям; xargs grep ограничивает временным окном или шаблоном; cut -d' ' -fN извлекает одно поле; sort | uniq -c | sort -rn — идиом ранжирования для любой гистограммы счётчиков; awk обрабатывает многопольную арифметику и вычисленные показатели за один проход. Строй конвейер инкрементально — добавляй одну стадию за раз и проверяй вывод перед добавлением следующей. uniq -c требует отсортированного ввода. awk правильно использовать, когда нужны условия или арифметика; sort | uniq -c — когда нужны ранжированные счётчики. Вместе они отвечают на вопросы инцидентов за секунды на гигабайтных логах без установки чего-либо дополнительного.

Практика

Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.

вспомнитьприменитьуглубить0 из 5 завершено

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources6
expand
  1. 01
  2. 02
  3. 03
  4. 04
  5. 05
  6. 06

Trademarks belong to their respective owners. Editorial reference only.