第11章 · 実例 2

100,000 行の Apache ログを bash パイプで解析

第 10 章「AIに任せる仕事を見極める」の 2 番目の角度: ログ解析はエージェントを呼ばず bash パイプ

章のどの主張に対応するか

Linux コマンドラインでの一括処理 ── AI 利用料ゼロ。 同じ処理を AI エージェントに頼むと、約 60 分、AI 利用料約 $5。1,200 倍の速さ

(章本文「実例: 数字で見る」より)

example-1 が「画像 1,000 枚を WebP 化」(I/O ヘビーな繰り返し処理)、 これは テキスト処理の繰り返し ── ログ解析を実演する。

やること

100,000 行(約 18 MB)の Apache combined log を生成して、6 種類の業務的な クエリを awk + sort + uniq のパイプで解く:

クエリ 内容
Q1 総リクエスト数 + ステータスコード分布
Q2 アクセス上位 10 IP
Q3 5xx エラーが起きた時間帯
Q4 404 になった URL 上位 10
Q5 攻撃疑いの IP(複数の攻撃 URL を試行)
Q6 1 分間のリクエスト数推移

すべて 0.04〜0.1 秒 で完了。

構成

example-2/
├── README.md
├── generate_log.py    ── 100,000 行のサンプルログ生成
├── Makefile           ── 6 クエリの bash パイプ
├── results.md
├── access.log         ── 入力 (約 18 MB, .gitignore)
└── out/
    ├── q1-status.txt
    ├── q2-top-ips.txt
    ├── q3-5xx-hours.txt
    ├── q4-404-paths.txt
    ├── q5-attackers.txt
    └── q6-rps.txt

実行

make clean && make all

なぜこれが「実例」になるのか

「ログから攻撃者を見つけて」「エラーの傾向を集計して」── これは 典型的に AI エージェントに頼みたくなる作業。でも:

エージェント方式(参考):

  1. 100,000 行のログをコンテキストに渡す → コンテキスト窓を超える
  2. ファイルを部分的に読ませる → 順次読みで遅い
  3. グレッパー的なツール呼び出しを LLM が書く → どうせ awk/grep
  4. 結果を集計させる → ハルシネーション(数値の)
  5. 1 回 60 分 / $5

bash パイプ方式(このフォルダ):

awk '$9 ~ /^5/ {print substr($4, 14, 5)}' access.log | sort | uniq -c | sort -rn | head

これが章で言う「コードに凍結する」の典型例。

「LLM を呼ぶべき場合」との境界

# LLM を呼ばない:集計、フィルタ、上位 N 抽出
awk '$9 == 500' access.log | wc -l    # 5xx の件数
sort | uniq -c | sort -rn              # ランキング

# LLM を呼ぶべき:意図の判断、自然言語の要約
# 例: 「攻撃ログを見て、何の脆弱性を狙っているか教えて」
# → 攻撃 URL のパターン(`/.env`, `/wp-login.php`...)を Claude が解釈

集計はコード、解釈は AI ── これが境界。 このフォルダは集計側を最小実装で示す。


計測結果 — 第 10 章 example-2

実行環境: Linux 6.18 / awk + sort + uniq(GNU coreutils)

ログ規模

項目 数値
行数 100,000 行
サイズ 約 18 MB
期間 2026-05-01(2 秒間隔の架空ログ)

クエリ実行時間(主目的)

クエリ コマンド要約 実行時間
Q1 ステータスコード集計 awk '{c[$9]++}' 0.05 秒
Q2 上位 IP awk | sort | uniq -c | sort -rn 0.09 秒
Q3 5xx の時間帯 awk '$9~/^5/' | sort | uniq -c 0.04 秒
Q4 404 の URL awk '$9==404' | sort | uniq -c 0.05 秒
Q5 攻撃 IP 検出 awk + uniq + 集約 0.05 秒
Q6 1 分ごとの RPS awk | sort | uniq -c 0.05 秒
合計 約 0.3 秒

100,000 行 × 6 クエリ = 600,000 行分の処理を 0.3 秒

エージェント方式との比較

項目 エージェント bash パイプ
6 クエリの実行 約 60 分 × 6 = 6 時間 0.3 秒
1 回の AI 利用料 $5 × 6 = $30 $0
結果の正確性 ハルシネーション可能性あり awk は計算ミスしない
再現性 プロンプト次第で揺れる 同じ入力 → 同じ出力
ログサイズの上限 コンテキスト窓 無制限(ストリーミング)

差は 約 70,000 倍

実際の出力(抜粋)

Q1 ステータスコード分布

  200 : 80,809 件 (80.8%)
  304 :  6,646 件 (6.6%)
  404 :  9,292 件 (9.3%)
  500 :  3,253 件 (3.3%)
  401 :    900 件 (0.9%)
  403 :    100 件 (0.1%)

  total: 100,000 件

Q2 上位 IP

   5047 203.0.113.42    ← 突出
    558 198.51.100.136
    546 198.51.100.169
    ...

203.0.113.425,047 件(2 位の 9 倍)── 異常。

Q5 攻撃疑いの検出(2 種類以上の攻撃 URL を試行した IP)

  203.0.113.42    攻撃 URL 5 種

Q2 で「異常に多い IP」、Q5 で「実際に攻撃 URL を試している IP」── これが 一致したので、フィルタ列に追加してブロック が次の自然な行動。

iptables -A INPUT -s 203.0.113.42 -j DROP

これも bash 1 行。

Q4 404 の URL 上位

   1047 /
    604 /static/style.css   ← デプロイ漏れの疑い
    418 /static/main.js     ← 同上
    362 /.env               ← 攻撃試行
    348 /config.php         ← 同上

CSS / JS の 404 はデプロイの問題、.env などは攻撃。運用判断に 直結する数字 が秒で出る。

なぜ awk なのか

awk '{c[$9]++} END {for (s in c) print s, c[s]}' access.log

LLM に「awk で…」と頼むと 8 割は一発で動く9 割の運用判断を これでカバーできる。

残り 1 割の「文字列の意味」「パターンの解釈」だけ、Claude に渡す。

来月の運用

*/15 * * * *   make analyze >> /var/log/web-analytics.log 2>&1
0    9 * * 1   make analyze | mail -s "Weekly access report" admin@example.com

15 分ごとに実行 / 月曜朝にメールで届く ── すべて月額 0 円。

再現手順

make clean && make all

依存ゼロ(awk / sort / uniq は標準で入っている)。

ファイル一覧

out/

第11章「AIに任せる仕事を見極める」に戻る