ログファイルの解析
5 万行を目で追っている
障害の報告を受けて開いたログが 5 万行あるとき、上から読んでも答えは出ません。知りたいのは「どの相手からの、どんな要求が、何件失敗したか」であって、1 行ずつの中身ではないからです。
まず、扱う形を見ます。Web サーバーのアクセスログは、1 行が空白区切りで並んだ表のような作りをしています。
プレーンテキスト
192.0.2.47 - - [19/May/2026:09:12:35 +0900] "GET /api/items HTTP/1.1" 500 91
192.0.2.11 - - [19/May/2026:09:12:36 +0900] "GET /api/users HTTP/1.1" 200 1234左から 1 列目が接続元、9 列目が応答の番号です。列で数えられる形になっている、という点が出発点になります。
一気に書こうとして、どこで間違えたか分からなくなる
長いつなぎを一度に書くと、結果が空になったときに原因の場所が特定できません。1 段ずつ足して、そのつど出力を見ます。
まず、見たい行だけに絞ります。
ターミナル
$ grep ' 500 ' access.log | head -3
192.0.2.47 - - [19/May/2026:09:12:35 +0900] "GET /api/items HTTP/1.1" 500 91
192.0.2.47 - - [19/May/2026:09:12:41 +0900] "GET /api/items HTTP/1.1" 500 88
192.0.2.9 - - [19/May/2026:09:13:02 +0900] "GET /api/items HTTP/1.1" 500 90絞れていることを確かめてから、欲しい列だけを取り出します。
ターミナル
$ grep ' 500 ' access.log | awk '{print $1}' | head -3
192.0.2.47
192.0.2.47
192.0.2.9ここまで来れば、あとは同じ値を数えるだけです。
ターミナル
$ grep ' 500 ' access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -3
58 192.0.2.47
12 192.0.2.9
3 192.0.2.311 台だけ突出していると分かりました。絞る、取り出す、数える。この 3 段が、ログ解析のほとんどを占めます。
数えたはずなのに、同じ値が何度も出てくる
uniq -c の前の sort を落とすと、件数が合いません。uniq が見るのは隣り合った行だけで、離れた場所にある同じ値は別のものとして数えられるためです。並べてから数える、と手順で覚えてください。
最後の sort -rn は数として大きい順に並べ替える指定です。-n を付けないと文字として並ぶので、100 より 99 が上に来ます。
対象が圧縮済みの
access.log.1.gzなら、grepの代わりにzgrepを使うと展開せずにそのまま絞れます。systemd の管理下にあるサービスのログは、ファイルではなくjournalctl -u サービス名から取り出します。
課題
- grep を使って ERROR 行をカウントする
- 結果として 3 のみを出力する