順番に読み進めながら学べます

ログ集計レポート — 引数・関数・連携の総仕上げ

この記事は、基礎コマンドからシェルスクリプトまでLinuxの実践的なスキルを1からマスターする「Linux入門講座の一部」です。
log=${1:-access.log} で対象ログを受け取り、forループとgrep -c・awk '{sum+=$1}' 連携で集計し、here-docレポートとexitコードにまとめる構成を、図解と端末で実習します。

要素を1本に統合する — ログ集計レポートの骨格

ここまでに学んだ変数・位置パラメータ($1)・条件分岐([ ]if)・ループ(for / while)・関数(name() { }local)・入力読込(while read … done < file)・コマンド連携($(...))・出力(>>と here-doc)を、1 本の実用スクリプトに組み合わせます

題材は運用で最も多い「ログ集計レポート」です。

実用スクリプトは、引数で対象ログとしきい値を受け取り、入力チェックをしてから集計し、結果をレポートにまとめ、最後に終了コードを返す流れで組みます

集計部分はgrepで件数、awkで合計、sedで整形といったコマンドと連携させ、繰り返しは関数とループにまとめると読みやすくなります。

位置パラメータが空のときは既定値${1:-access.log}で補います。

vi mini.sh   # エディタで開き、次の内容を書いて :wq で保存
#   #!/bin/sh
#   log=${1:-access.log}              # 引数が無ければ既定値
#   count_status() {                  # 状態コードの件数を返す関数
#     grep -c " $1\$" "$log"
#   }
#   if [ ! -f "$log" ]; then          # 入力チェック
#     echo "not found: $log" >&2
#     exit 1
#   fi
#   for s in 200 403 500; do          # 状態コードごとに集計
#     echo "$s : $(count_status $s)"
#   done
#   exit 0
chmod +x mini.sh
実用スクリプトの処理の流れ
引数を受ける$1 log / $2 limit入力チェック[ -f "$log" ]集計関数grep / awk 連携while read で1 行ずつ処理here-docレポート出力exit 0 / 1成否を返す① 準備② 集計③ 出力
引数受け取り → 入力チェック → 集計(コマンド連携)→ レポート出力 → 終了コードの順に組みます。
要素本スクリプトでの使い所
変数name=...ログ名・出力先・しきい値を 1 か所で管理するlog=${1:-access.log}
引数$1 / ${1:-既定}対象ログとしきい値をコマンドラインから受け取るlimit=${2:-1}
条件[ -f f ] / ifログの存在確認・しきい値超過の判定をするif [ ! -f "$log" ]; then exit 1; fi
ループfor / while read状態コードごとの集計・1 行ずつの読み取りfor s in 200 403 500; do … done
関数name() { … }集計処理を名前付きでまとめ再利用するcount_status() { grep -c " $1\$" "$log"; }
入力読込while read … < fログを 1 行ずつ読み URL ごとに数えるwhile read line; do … done < "$log"
連携$(grep -c …) / awk件数・合計をコマンド置換で取り込むn=$(grep -c ' 500$' "$log")
出力>> / here-doc集計値を定型レポートに書き出すcat > "$out" <<REPORT … REPORT

引数・条件・関数・ループ・コマンド連携を統合した集計スクリプトを作って実行します。

① 素材ログをprintf '12 GET /home 200\n34 GET /login 200\n5 GET /admin 403\n88 GET /api 500\n7 GET /home 200\n21 POST /api 500\n' > access.logで作成してください。

vi summary.shsummary.shを開き、iで挿入モードに入って、引数・条件・関数・ループ・連携を統合した集計処理を書き、Esc:wqで保存してください(書く内容は解答パネルからコピーして貼り付けられます)。

chmod +x summary.shで実行権を付与してください。

./summary.shで実行し、画面に出る状態コード別の集計を確認してください。(正しく実行できれば解説が表示されます)

Linux console
0 / 3 実行済み
Loading Linux Terminal...

入力を読み連携で仕上げる — while read と grep / awk / sed

1 行ずつの細かな処理はwhile read line; do … done < fileで行います。

読み取った各行に対しgrepで絞り込み、awkで列を集計し、sedで表記をそろえる、といった連携を関数の中で組み合わせると、集計ロジックを部品として再利用できます

sed 's/^GET /[GET] /'のように整形を挟むと、レポートの体裁を統一できます。

仕上げは here-doc で定型レポートに集計値を埋め込み、しきい値を超えたら警告を追記してexit 1、正常ならexit 0を返します。

引数の 2 つ目をしきい値として${2:-100}で受け取り、if [ "$err" -gt "$limit" ]のように数値比較すると、運用で使える判定付きレポートになります。

基礎で学んだgrep / awk / sedを、シェルスクリプトの制御構造の中で連携させるのが集大成です

vi scan.sh   # エディタで開き、次の内容を書いて :wq で保存
#   #!/bin/sh
#   log=${1:-access.log}
#   limit=${2:-1}
#   err=$(grep -c ' 500$' "$log")     # 500 の件数を連携で取得
#   while read line; do                # 1 行ずつ読む
#     echo "$line" | sed 's/^/log: /'  # 整形して表示
#   done < "$log"
#   if [ "$err" -gt "$limit" ]; then   # しきい値で判定
#     echo "WARN: too many 500"; exit 1
#   fi
#   exit 0
chmod +x scan.sh
入力読込と grep / awk / sed の連携
while read line< access.log1 行ずつ読み取るgrep / awk / sed絞り込み・集計整形を連携here-doc +if しきい値判定レポート +exit 0 / 1① 1 行ずつ読む② 連携で集計③ 判定して出力
while readで 1 行ずつ取り込み、grep / awk / sedと連携して判定付きレポートに仕上げます。

入力をしきい値で受け取り、while read と grep / awk / sed の連携で判定付きレポートに仕上げます。

① 素材ログをprintf '12 GET /home 200\n34 GET /login 200\n5 GET /admin 403\n88 GET /api 500\n7 GET /home 200\n21 POST /api 500\n' > access.logで作成してください。

vi audit.shaudit.shを開き、iで挿入モードに入って、while read と grep / awk / sed 連携の判定付きレポート処理を書き、Esc:wqで保存してください(書く内容は解答パネルからコピーして貼り付けられます)。

chmod +x audit.shで実行権を付与してください。

./audit.sh access.log 1のように引数を渡して実行し、生成されたreport.txtと画面の判定結果を確認してください。

Linux console
0 / 3 実行済み
Loading Linux Terminal...

引数のしきい値で合否を分ける — 集計と終了コードの統合

前半の引数受け取りと集計、後半の判定と終了コードを 1 本にまとめ、運用で使える「合否判定付きレポート」に仕上げます。

第1引数でしきい値を受け取り、grep -cawkで集計した件数がしきい値以上なら警告としてexit 1、未満なら正常としてexit 0を返します。

呼び出し元はこの終了コードで成否を判定できます

数値比較の-gtは「より大きい」、-geは「以上」で、しきい値ちょうどの値の扱いが変わります。

実践 2 の[ "$err" -gt "$limit" ]は件数がしきい値と同じだと条件を満たさず、実践 3 の[ "$err" -ge "$limit" ]は同じ値でも警告になります。

境界の合否を決める要なので、用途に合わせて選びます。

しきい値で合否を分ける
err=$(grep -c ' 500$')err ≥ limitWARN + exit 1err < limitOK + exit 0しきい値以上未満警告正常
集計した件数をしきい値と-geで比べ、以上なら警告してexit 1、未満なら正常でexit 0を返します。

引数で渡したしきい値で集計結果の合否を分ける、判定付きレポートスクリプトを作って実行します。

① 素材ログをprintf '12 GET /home 200\n34 GET /login 200\n5 GET /admin 403\n88 GET /api 500\n7 GET /home 200\n21 POST /api 500\n' > access.logで作成してください。

vi report.shreport.shを開き、iで挿入モードに入って、しきい値で合否を分ける判定付きレポート処理を書き、Esc:wqで保存してください(書く内容は解答パネルからコピーして貼り付けられます)。

chmod +x report.shで実行権を付与してください。

./report.sh 2のように第1引数でしきい値を渡して実行し、画面の判定結果と生成されたreport.txtを確認してください。

./report.sh 3のように引数の数値を変えて再実行し、合否が変わることも確認してください。

Linux console
0 / 3 実行済み
Loading Linux Terminal...
QUIZ

理解度チェック

まずは1問ずつ答えてみましょう。

Q1第1引数が渡されなかったときに既定値access.logを使う書き方はどれですか?

Q2ファイルを1行ずつ読み取って処理する書き方はどれですか?

Q3しきい値を超えたときに呼び出し元へ異常を伝えるにはどうしますか?