0Pricing
Linux Command Line & Bash Scripting Mastery · Урок

Отслеживание журналов в реальном времени и потоковые оповещения

Отслеживайте и фильтруйте потоки журналов в реальном времени, чтобы мгновенно запускать оповещения при появлении шаблонов ошибок

«Отслеживание журналов в реальном времени и потоковые оповещения» — бесплатный урок Linux Command Line & Bash Scripting Mastery на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Linux Command Line & Bash Scripting Mastery, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Linux Command Line & Bash Scripting Mastery содержит 4 уроков всего.

Почему важно отслеживать журналы в реальном времени

В промышленных системах журнальные файлы постоянно растут. Если ждать сообщения о проблеме и только потом изучать журналы, простой уже успеет обойтись Вам дорого. Отслеживание журналов в реальном времени позволяет наблюдать за событиями сразу после их записи и немедленно реагировать на сбои, события безопасности и ухудшение производительности.

  • Веб-серверы записывают по одной строке на каждый запрос — ошибки появляются сразу
  • Службы приложений записывают трассировки стека в момент возникновения исключения
  • Системы аутентификации регистрируют неудачные попытки входа в реальном времени

Основной инструмент Unix для этого — tail -f, используемый вместе с утилитами фильтрации и оповещения, чтобы превращать необработанные потоки журналов в полезные сигналы.

tail -f: отслеживание текущего журнала

tail -f (отслеживание) оставляет файл открытым и выводит новые строки по мере их добавления. Это самый простой и повсеместно доступный инструмент для работы с журналами в реальном времени.

Распространённые варианты использования:

  • tail -f /var/log/syslog — отслеживать системный журнал
  • tail -n 50 -f app.log — показать последние 50 строк, а затем продолжить отслеживание
  • tail -f /var/log/nginx/access.log — отслеживать запросы nginx в реальном времени

Нажмите Ctrl+C, чтобы остановить команду. Процесс продолжает работать, пока Вы его не отмените или не закроете терминал.

#!/usr/bin/env bash
# Simulate a live log and follow it
LOGFILE='/tmp/demo_app.log'

# Write a header
echo '[INFO] Application started' >> "$LOGFILE"

# In a real scenario you would run:
# tail -f "$LOGFILE"
# Below we demonstrate tail showing the last 3 lines then exit
tail -n 3 "$LOGFILE"

tail -F: работа после ротации журнала

Многие системы ротируют журнальные файлы в полночь или при достижении определённого размера. В этот момент исходный файл переименовывается (например, app.log.1), а создаётся новый app.log. При использовании tail -f Вы незаметно продолжаете читать старый переименованный файл и пропускаете весь новый вывод.

tail -F (с прописной F) решает эту проблему, отслеживая имя файла, а не файловый дескриптор. Когда файл исчезает и появляется снова, tail -F автоматически открывает его заново и продолжает отслеживание.

  • В рабочих сценариях всегда предпочитайте tail -F вместо tail -f
  • Команда работает с logrotate, newsyslog и драйверами журналов Docker, которые ротируют файлы
# Follow nginx access log, surviving log rotation
tail -F /var/log/nginx/access.log

# Follow multiple files simultaneously
tail -F /var/log/nginx/access.log /var/log/nginx/error.log

Фильтрация потока с помощью grep

Отслеживать необработанный поток загруженного журнала утомительно — активный веб-сервер может записывать сотни строк в секунду. Передайте вывод tail -F в grep, чтобы выделить только интересующие Вас шаблоны.

Основные параметры grep для потоковой обработки:

  • --line-buffered — немедленно сбрасывать каждую найденную строку вместо буферизации; это обязательно в конвейерах, иначе вывод будет задерживаться или теряться
  • -i — поиск без учёта регистра
  • -E — расширенные регулярные выражения для чередования (error|warn|crit)
  • -v — инвертировать условие поиска (исключать строки)
# Show only ERROR and WARN lines from a live application log
tail -F /var/log/myapp/app.log | grep --line-buffered -Ei 'error|warn|critical'

# Follow nginx and exclude health-check requests
tail -F /var/log/nginx/access.log | grep --line-buffered -v '/health'

Добавление временных меток и контекста с помощью awk

В журнальных строках иногда не хватает контекста, который помогает при первичном анализе. Вы можете обогащать поток в реальном времени с помощью awk — добавлять местную временную метку, извлекать поля или изменять формат вывода для удобства чтения.

awk также работает в потоковом режиме (с буферизацией по строкам) при передаче данных через конвейер, поэтому его безопасно использовать в конвейерах реального времени без дополнительных параметров.

# Prepend a reception timestamp to every ERROR line
tail -F /var/log/myapp/app.log | \
  grep --line-buffered -i 'error' | \
  awk '{ print strftime("[%Y-%m-%d %H:%M:%S]"), $0; fflush() }'

# Extract HTTP status code (field 9) and URL (field 7) from nginx combined log
tail -F /var/log/nginx/access.log | \
  awk '{ print $9, $7; fflush() }' | \
  grep --line-buffered '^5'

Отправка оповещений с помощью вебхуков Slack

Фильтрация — это только половина задачи: обнаружив шаблон ошибки, необходимо уведомить кого-либо. Входящий вебхук Slack позволяет отправить сообщение в канал с помощью одного вызова curl; для этого не нужны SDK Slack или какие-либо учётные данные, кроме URL вебхука.

Шаблон таков: отфильтровать поток и отправить HTTP POST для каждой подходящей строки.

#!/usr/bin/env bash
# Real-time alert: send every ERROR line to a Slack channel
LOGFILE='/var/log/myapp/app.log'
WEBHOOK_URL='https://hooks.slack.com/services/T000/B000/XXXX'

tail -F "$LOGFILE" | grep --line-buffered -i 'error' | while IFS= read -r line; do
  payload=$(printf '{"text":"*[ERROR ALERT]*\n%s"}' "$line")
  curl -s -o /dev/null -X POST -H 'Content-Type: application/json' \
    -d "$payload" "$WEBHOOK_URL"
done

Ограничение частоты оповещений для предотвращения шума

Шквал записей в журнале может порождать тысячи строк ошибок в минуту. Отправка одного сообщения Slack на каждую строку переполнит канал и приведёт к усталости от оповещений. Необходимо ограничение частоты — отправить оповещение, а затем подавлять последующие уведомления в течение периода ожидания.

Для этого используется простой файл временной метки: записывается время отправки последнего оповещения, а новое оповещение не отправляется, если период ожидания ещё не истёк.

#!/usr/bin/env bash
# Alert on ERROR lines but no more than once every 60 seconds
LOGFILE='/var/log/myapp/app.log'
WEBHOOK_URL='https://hooks.slack.com/services/T000/B000/XXXX'
COOLDOWN=60
LAST_ALERT_FILE='/tmp/last_alert_ts'

tail -F "$LOGFILE" | grep --line-buffered -i 'error' | while IFS= read -r line; do
  now=$(date +%s)
  last=0
  [ -f "$LAST_ALERT_FILE" ] && last=$(cat "$LAST_ALERT_FILE")

  if (( now - last >= COOLDOWN )); then
    echo "$now" > "$LAST_ALERT_FILE"
    payload=$(printf '{"text":"*[ERROR ALERT]*\n%s"}' "$line")
    curl -s -o /dev/null -X POST -H 'Content-Type: application/json' \
      -d "$payload" "$WEBHOOK_URL"
    echo "[$(date)] Alert sent: $line"
  else
    echo "[$(date)] Suppressed (cooldown): $line"
  fi
done

Подсчёт всплесков ошибок с помощью скользящего окна

Иногда одна строка ошибки не имеет большого значения, но 20 ошибок за 30 секунд — это серьёзная проблема. Счётчик на основе скользящего окна позволяет отправлять оповещения только при превышении порога частоты ошибок, сокращая число ложных срабатываний.

Этот приём сохраняет временную метку эпохи для каждого подходящего события во временном файле, а затем перед принятием решения об отправке оповещения подсчитывает, сколько событий попало в окно.

#!/usr/bin/env bash
# Alert when more than 10 errors occur within any 60-second window
LOGFILE='/var/log/myapp/app.log'
WINDOW=60
THRESHOLD=10
TS_FILE='/tmp/error_timestamps'
WEBHOOK_URL='https://hooks.slack.com/services/T000/B000/XXXX'

tail -F "$LOGFILE" | grep --line-buffered -i 'error' | while IFS= read -r line; do
  now=$(date +%s)
  echo "$now" >> "$TS_FILE"

  # Keep only timestamps within the window
  cutoff=$(( now - WINDOW ))
  tmp=$(mktemp)
  awk -v c="$cutoff" '$1 > c' "$TS_FILE" > "$tmp" && mv "$tmp" "$TS_FILE"

  count=$(wc -l < "$TS_FILE")
  if (( count > THRESHOLD )); then
    msg="*[BURST ALERT]* ${count} errors in ${WINDOW}s — last: ${line}"
    curl -s -o /dev/null -X POST -H 'Content-Type: application/json' \
      -d "{\"text\":\"$msg\"}" "$WEBHOOK_URL"
    # Clear to avoid re-alerting until next burst
    > "$TS_FILE"
  fi
done

journalctl -f: отслеживание журналов systemd

В современных системах Linux (RHEL, Ubuntu 20.04+, Debian 10+) службы записывают данные в журнал systemd, а не в обычные текстовые файлы. journalctl -f — это аналог tail -F для журнала.

Полезные параметры:

  • -u myapp.service — отслеживать только указанную единицу
  • -p err — фильтровать по приоритету (emerg, alert, crit, err, warning, notice, info, debug)
  • --since '5 min ago' — начать с относительного момента времени
  • -o json — выводить структурированный JSON для машинного разбора
# Follow only error-and-above entries for nginx
journalctl -f -u nginx.service -p err

# Stream journal as JSON and extract MESSAGE field with jq
journalctl -f -u myapp.service -o json | \
  jq --unbuffered -r 'select(.PRIORITY <= "3") | .MESSAGE'

multitail и цветной мониторинг нескольких источников

Когда необходимо одновременно отслеживать несколько источников журналов, multitail разделяет терминал на панели — каждая отслеживает отдельный файл или команду — и при необходимости выделяет шаблоны цветом.

Если multitail не установлен, лёгкой альтернативой на чистом BASH будет добавление к каждому потоку имени источника и объединение потоков в одном представлении.

# multitail: watch nginx access + error + app log in split panes
# (requires: apt install multitail  or  brew install multitail)
multitail /var/log/nginx/access.log /var/log/nginx/error.log /var/log/myapp/app.log

# Pure-Bash alternative — merge three streams with labeled prefixes
(
  tail -F /var/log/nginx/access.log | sed --unbuffered 's/^/[nginx-access] /' &
  tail -F /var/log/nginx/error.log  | sed --unbuffered 's/^/[nginx-error]  /' &
  tail -F /var/log/myapp/app.log    | sed --unbuffered 's/^/[myapp]        /' &
  wait
)

Создание автономной службы оповещений

Объединяя всё изученное в этом уроке, служба оповещений промышленного уровня должна:

  • Надёжно отслеживать журнальный файл с помощью tail -F
  • Фильтровать критические шаблоны с помощью буферизованного grep
  • Ограничивать частоту уведомлений, чтобы избежать усталости от оповещений
  • Записывать собственную активность, чтобы можно было проверить отправленные сообщения
  • Работать как фоновый процесс под управлением systemd или диспетчера процессов

Приведённый ниже сценарий — минимальная, но полноценная служба, которую можно поместить в /usr/local/bin/ и управлять ею с помощью systemd.

#!/usr/bin/env bash
# log_alert_daemon.sh — tail a log and fire Slack alerts with cooldown
set -euo pipefail

LOGFILE=${1:-'/var/log/myapp/app.log'}
PATTERN=${2:-'error|critical|fatal'}
WEBHOOK_URL=${SLACK_WEBHOOK_URL:?'Set SLACK_WEBHOOK_URL env var'}
COOLDOWN=${ALERT_COOLDOWN:-120}
DAEMON_LOG='/var/log/log_alert_daemon.log'
LAST_SENT_FILE='/tmp/log_alert_last_sent'

log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$DAEMON_LOG"; }

log "Starting alert daemon: watching $LOGFILE for pattern: $PATTERN"

tail -F "$LOGFILE" | grep --line-buffered -Ei "$PATTERN" | while IFS= read -r line; do
  now=$(date +%s)
  last=0
  [ -f "$LAST_SENT_FILE" ] && last=$(cat "$LAST_SENT_FILE")

  if (( now - last >= COOLDOWN )); then
    echo "$now" > "$LAST_SENT_FILE"
    msg=$(printf '{"text":"*[ALERT]* %s\n%s"}' "$(hostname)" "$line")
    if curl -s -o /dev/null -w '%{http_code}' -X POST \
         -H 'Content-Type: application/json' -d "$msg" "$WEBHOOK_URL" | grep -q '^200$'; then
      log "Alert sent: $line"
    else
      log "Alert FAILED to send: $line"
    fi
  else
    log "Suppressed (cooldown ${COOLDOWN}s): $line"
  fi
done

Проверка знаний: потоковые конвейеры журналов

Проверьте, насколько хорошо Вы понимаете отслеживание журналов в реальном времени и потоковые оповещения.

Конвейер Bash отслеживает журнальный файл и отправляет оповещение Slack для каждой подходящей строки. Во время шквала записей за 10 секунд записываются 3 000 строк ошибок. Какое единственное изменение лучше всего предотвратит отправку скриптом 3 000 сообщений в канал Slack?

Итоги урока: отслеживание журналов и потоковые оповещения в реальном времени

В этом уроке Вы с нуля создали полноценный конвейер наблюдаемости журналов в реальном времени:

  • tail -F отслеживает журнальный файл по имени и переживает ротацию журналов — в рабочих системах всегда предпочитайте эту команду вместо tail -f
  • grep --line-buffered фильтрует поток в реальном времени без добавления задержки; всегда добавляйте этот параметр в команды grep, соединённые конвейером
  • awk с fflush() безопасным для потоковой обработки способом обогащает каждую строку временными метками или извлечёнными полями
  • Вебхуки Slack через curl доставляют оповещения одним HTTP POST — SDK не требуется
  • Файлы периода ожидания предотвращают усталость от оповещений во время шквалов записей, устанавливая минимальный интервал между уведомлениями
  • Счётчики на основе скользящего окна обнаруживают всплески ошибок (оповещения по частоте), а не реагируют на каждую отдельную строку
  • journalctl -f — встроенный в systemd аналог tail -F со встроенной фильтрацией по приоритету и выводом JSON
  • Автономный сценарий службы оповещений объединяет все эти приёмы и для надёжной работы в промышленной среде может управляться systemd

Эти базовые средства образуют основу любого пользовательского конвейера наблюдаемости — сторонний агент не требуется.

Часто задаваемые вопросы

Урок «Отслеживание журналов в реальном времени и потоковые оповещения» бесплатный?

Да — полный текст урока «Отслеживание журналов в реальном времени и потоковые оповещения» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Linux Command Line & Bash Scripting Mastery, подпишись на CoddyKit PRO. Курс Linux Command Line & Bash Scripting Mastery содержит 4 уроков всего.

Чему я научусь в уроке «Отслеживание журналов в реальном времени и потоковые оповещения»?

Отслеживайте и фильтруйте потоки журналов в реальном времени, чтобы мгновенно запускать оповещения при появлении шаблонов ошибок Ты практикуешь Linux Command Line & Bash Scripting Mastery с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Linux Command Line & Bash Scripting Mastery?

Предыдущий опыт не требуется. Linux Command Line & Bash Scripting Mastery на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Отслеживание журналов в реальном времени и потоковые оповещения»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Linux Command Line & Bash Scripting Mastery?

Да. Каждый урок Linux Command Line & Bash Scripting Mastery включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Масштабный разбор веб-журналов и журналов приложений
  2. Отслеживание журналов в реальном времени и потоковые оповещения
  3. Запросы к journald с journalctl в скриптах
  4. Вычисление показателей и гистограмм из потоков журналов
← Назад к Linux Command Line & Bash Scripting Mastery