今更ながらAWKの勉強を始めた
先輩「サーバーリプレイスのための調査よろしく〜。サーバーに関する有識者はいないし仕様書もないけど...」
私「わかりました〜」(いつものことじゃん...)
ということでサーバー調査が始まりました。
AIに聞けば調査も楽々進むわけで困りませんね。
困りませんね...?
調査内容が誤っていた場合に責任を追うのは私なので、調査が楽でも中身を把握していないといけません。確かに調査には困りませんが、サーバーが停止した瞬間にトラブルが発生したら問題です。
AIが「何を」「どうやって」調べているのかを理解するためにAWKの勉強を始めました。
AWKの基本
コマンドの基本形式は以下の通り。
awk 'パターン { アクション }' ファイル
パターンとアクションはシングルクォーテーションで囲んで、さらにアクションは波括弧で囲うのね。
ファイルを1行ずつ読み込んで、パターンに一致したらアクションを実行する。
うん、難しくない。
パターンに一致させる
私がAWKを使用する場面は今のところログ調査くらい。apacheだったりnginxだったり。
パターン一致させるには、一致させたい箇所を抽出しなければならない。
次の記法を使用する。
| 記法 | 意味 |
|---|---|
| \$0 | 行全体 |
| \$1, \$2, ... | 1番目、2番目...のフィールド |
| NF | その行のフィールド数 |
| NR | 行番号 |
Apacheのログが以下とする。
※Claudeで作成したサンプル
192.168.1.10 - - [17/Oct/2026:00:01:02 +0900] "GET /index.html HTTP/1.1" 200 1234 "-" "Mozilla/5.0"
192.168.1.11 - - [17/Oct/2026:00:01:15 +0900] "GET /products?id=3 HTTP/1.1" 200 5120 "-" "Mozilla/5.0"
192.168.1.10 - - [17/Oct/2026:00:02:30 +0900] "POST /login HTTP/1.1" 302 0 "-" "Mozilla/5.0"
192.168.1.12 - - [17/Oct/2026:00:03:45 +0900] "GET /missing.html HTTP/1.1" 404 512 "-" "curl/8.0"
192.168.1.10 - - [17/Oct/2026:01:04:10 +0900] "GET /index.html HTTP/1.1" 200 1234 "-" "Mozilla/5.0"
192.168.1.13 - - [17/Oct/2026:01:05:00 +0900] "GET /api/items HTTP/1.1" 500 0 "-" "Mozilla/5.0"
192.168.1.11 - - [17/Oct/2026:01:06:20 +0900] "GET /index.html HTTP/1.1" 200 1234 "-" "Mozilla/5.0"
192.168.1.12 - - [17/Oct/2026:02:07:33 +0900] "GET /missing.html HTTP/1.1" 404 512 "-" "curl/8.0"
IPアドレスとパスだけを出力する
この場合、パターンは省略できる。
必要な情報だけ出力できるのはいいね。
awk '{ print $1, $7}' access.log
>>192.168.1.10 /index.html
>>192.168.1.11 /products?id=3
>>...
404だけ抽出する
トラブル時によく使いそう。
awk '$9 == 404 { print $1, $7 }' access.log
>>192.168.1.12 /missing.html
>>192.168.1.12 /missing.html
アクセスの多いIPを抽出する
Webサーバーを公開するとあっという間にwp-adminとか.htaccessとかアクセスしようとするログが貯まるね〜。
使用履歴調査で使えるね。
awk '{ count[$1]++ } END { for (ip in count) print ip, count[ip] }' access.log | sort -k2 -nr
>>192.168.1.10 3
>>192.168.1.11 2
>>192.168.1.12 2
>>192.168.1.13 1
このコマンドは詳しくメモしておく。
{ count[$1]++ }
連想配列countに対して、IPアドレス($1)をキーにして、その値を1増やしている。
END for (ip in count) print ip, count[ip]
全ての行を読み込んだ後に一度だけ実行される。
配列のキーを取り出してipに代入しながらループして出力する。
| sort -k2 -nr
|パイプコマンドで出力をsortへ渡す。
-k2で2つ目のフィールドを指定し、-nrで数値比較かつ大きい順に並び替える。
今日はここまで
ひとまずここまでできれば大量のログから見たいログのみを抽出できるので、「ふーん、あのサーバーと通信しているのね」みたいなことを知ることができます。
手が勝手に動いてくれるレベルにはまだまだ遠いですがそのうち動くようになるでしょう。
tail /var/log/httpd/access_logは打ちすぎて午後の睡魔に負けていても勝手に手が動きます。