0Pricing
Linux Command Line & Bash Scripting Mastery · レッスン

リアルタイムのログ追跡とストリーミングアラート

ライブのログストリームを追跡・フィルタリングし、エラーパターンが現れた瞬間にアラートを発生させます。

「リアルタイムのログ追跡とストリーミングアラート」はCoddyKit上の無料Linux Command Line & Bash Scripting Masteryレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLinux Command Line & Bash Scripting Mastery学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Linux Command Line & Bash Scripting Masteryコースには全4レッスンが含まれています。

リアルタイムでログを追跡する重要性

本番システムでは、ログファイルが継続的に増加します。問題が報告されてからログを調べるのでは、すでにダウンタイムによる損失が発生しています。リアルタイムのログ追跡を使えば、イベントが書き込まれた瞬間にその進行を監視できるため、障害、セキュリティイベント、パフォーマンス低下に即座に対応できます。

  • Webサーバーはリクエストごとに1行を書き込むため、エラーがすぐに現れます
  • アプリケーションデーモンは、例外が発生した瞬間にスタックトレースを記録します
  • 認証システムは、失敗したログイン試行をリアルタイムで記録します

このための基本的なUnixツールがtail -fです。フィルタリングやアラートのユーティリティと組み合わせることで、生のログストリームを対応可能なシグナルに変換できます。

tail -f:ライブログの追跡

tail -f(follow)はファイルを開いたままにし、末尾に追加された新しい行を表示します。最もシンプルで、ほぼすべての環境で利用できるリアルタイムログツールです。

一般的な使用パターン:

  • 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によるストリームのフィルタリング

大量のログをそのまま追跡すると圧倒されます。稼働中のWebサーバーは毎秒数百行を書き込むことがあります。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 Webhookによるアラートの送信

フィルタリングは作業の半分にすぎません。エラーパターンを検出したら、誰かに通知する必要があります。Slackのincoming webhookを使えば、Slack SDKやWebhook URL以外の認証情報なしで、1回のcurl呼び出しによりチャンネルへメッセージをPOSTできます。

基本的なパターンは、ストリームをフィルタリングし、一致する各行について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

ノイズを防ぐアラートのレート制限

ログストームが発生すると、1分間に数千行のエラーが生成されることがあります。1行ごとに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

スライディングウィンドウによるエラーバーストのカウント

単発のエラー行には意味がない場合があります。しかし、30秒間に20件のエラーは深刻な問題です。スライディングウィンドウカウンターを使うと、エラー率がしきい値を超えた場合にのみアラートを発火でき、誤検知を減らせます。

この手法では、一致した各イベントのエポックタイムスタンプを一時ファイルに保存し、アラートを送るかどうかを判断する前に、ウィンドウ内に入るイベント数をカウントします。

#!/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がインストールされていない場合は、各ストリームの先頭にソース名を付けて1つのビューに統合する、軽量な純粋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またはsupervisorで管理するバックグラウンドプロセスとして実行する

次のスクリプトは、/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行のエラーが書き込まれました。スクリプトがSlackチャンネルに3,000件のメッセージを送りつけるのを最も効果的に防ぐ単一の変更はどれですか。

レッスンのまとめ:リアルタイムのログ追跡とストリーミングアラート

このレッスンでは、基本原理からリアルタイムのログ可観測性パイプラインを構築しました。

  • tail -Fはファイル名でログファイルを追跡し、ログローテーション後も追跡を続けます。本番環境では常にtail -fより優先してください
  • grep --line-bufferedは遅延を発生させずにライブストリームをフィルタリングします。パイプでgrepを使う場合は常にこのオプションを追加してください
  • fflush()付きのawkは、ストリーミングに安全な方法で各行にタイムスタンプや抽出したフィールドを追加します
  • curl経由のSlack Webhookは、SDKなしで1回のHTTP POSTによりアラートを送信します
  • クールダウンファイルは、通知間に最小間隔を設けることで、ログストーム中のアラート疲れを防ぎます
  • スライディングウィンドウカウンターは、個々の行に反応するのではなく、エラーバースト(率ベースのアラート)を検出します
  • journalctl -fはsystemdネイティブのtail -F相当機能であり、優先度フィルタリングとJSON出力を組み込みで備えています
  • 自己完結型のアラートデーモンスクリプトはこれらすべてのパターンを組み合わせ、本番環境での信頼性を確保するためにsystemdで管理できます

これらの基本要素を組み合わせれば、サードパーティ製エージェントなしで、あらゆるカスタム可観測性パイプラインの基盤を構築できます。

よくある質問

「リアルタイムのログ追跡とストリーミングアラート」レッスンは無料ですか?

はい。「リアルタイムのログ追跡とストリーミングアラート」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Linux Command Line & Bash Scripting Masteryコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Linux Command Line & Bash Scripting Masteryコースには全4レッスンが含まれています。

「リアルタイムのログ追跡とストリーミングアラート」で何を学びますか?

ライブのログストリームを追跡・フィルタリングし、エラーパターンが現れた瞬間にアラートを発生させます。 ブラウザで直接実行するハンズオンコードでLinux Command Line & Bash Scripting Masteryを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Linux Command Line & Bash Scripting Masteryを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのLinux Command Line & Bash Scripting Masteryは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「リアルタイムのログ追跡とストリーミングアラート」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このLinux Command Line & Bash Scripting Masteryレッスンでコードを書いて実行できますか?

はい。すべてのLinux Command Line & Bash Scripting Masteryレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 大規模なWeb・アプリケーションログの解析
  2. リアルタイムのログ追跡とストリーミングアラート
  3. スクリプトでjournalctlを使ったjournaldの検索
  4. ログストリームからのメトリクスとヒストグラムの計算
← Linux Command Line & Bash Scripting Masteryに戻る