本文へスキップ
BecomeCoder

シェルスクリプトコース · 第9章 実践 · レッスン41

ログ集計スクリプト ― 数えて報告する

ブラウザで完結

導入

「昨日のアクセスは何件で、エラーは何件で、どのIPが多かったか」。毎朝これを手で調べるのは無駄です。1本のスクリプトにして、cron で毎朝走らせましょう。

説明

集計は、パイプで組み立てた1行を $( ) で受け取り、関数で整えるのが基本形です。

#!/bin/bash
set -eu

LOG_FILE=/home/user/logs/access.log

# 見出しつきで出す小さな道具
section() {
  echo ""
  echo "=== $1 ==="
}

if [ ! -f "$LOG_FILE" ]; then
  echo "エラー: $LOG_FILE がありません" >&2
  exit 1
fi

section "サマリー"
TOTAL=$(wc -l < "$LOG_FILE")
ERR403=$(grep -c " 403" "$LOG_FILE")
ERR404=$(grep -c " 404" "$LOG_FILE")
echo "総アクセス数: $TOTAL"
echo "エラー応答: $((ERR403 + ERR404)) 件(403が $ERR403、404が $ERR404)"

section "IPごとのアクセス数(多い順)"
cut -d ' ' -f 1 "$LOG_FILE" | sort | uniq -c | sort -rn

section "ステータスの内訳"
cut -d ' ' -f 4 "$LOG_FILE" | sort | uniq -c | sort -rn

cut -d ' ' -f 1 | sort | uniq -c | sort -rn は、テキスト集計の黄金パターンです。

flowchart LR
    A["access.log"] --> B["cut -f 1<br/>(IP列を取り出す)"]
    B --> C["sort<br/>(同じものを隣に)"]
    C --> D["uniq -c<br/>(数える)"]
    D --> E["sort -rn<br/>(多い順に並べる)"]

uniq -c は「隣り合った同じ行」しか数えられないので、その前の sort が必須です。ここを忘れるのが定番のミスなので、sort | uniq -c はセットで覚えてください。

section() のような小さな関数は、地味ですが効きます。出力の体裁が揃い、あとで「Slackに送る」となったときも、この関数を差し替えるだけで済みます。

やってみよう

スクリプトを実行して、3つのセクションが出ることを確かめましょう。次に cut -d ' ' -f 1-f 3(パス)に変えて実行し、「よくアクセスされるページ」の集計に変わることを見てください。集計の軸を変えるのが1文字で済む——これがパイプの強さです。

演習

ステータスの内訳を出して、403 が2件あることを確認してください(2 403 のような行が出ます)。

ヒント1を見る

そのまま実行すれば「ステータスの内訳」に出ます。

ヒント2を見る

cut -d ' ' -f 4 logs/access.log | sort | uniq -c | sort -rn

実際に動かしてみよう

本文のサンプルや演習のコードは、コードブロック右上の「コピー」ボタンでコピーして、下のエディタに貼り付ければそのまま実行できます。

シェルスクリプト(シミュレート)

スクリプトを書くエディタと、それを動かす仮想シェルを読み込みます(本物のbashではなく、動きを再現した学習用の環境です)。
スクロールして表示された時点でも自動で読み込まれます。