導入
「昨日のアクセスは何件で、エラーは何件で、どの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