awkコマンドを使ってログを調べる
先日、自分のリリースしたものが派手に障害を起こしてしまい、影響範囲を調べるためにエラーログをあれこれいじる機会がありました。
こういう機会は無いに越したことはないのですが、その時に活躍したawkコマンドについて簡単にまとめておきます。
awkとは
awkは厳密にはコマンドではなく、それ自体がスクリプト言語のようです。単一のテキスト(ファイル)を整形したりするのに便利なツールです。
シェルスクリプトといえばPerlが思い浮かびますが、そこまでの学習コストを必要とせず、簡単にフィルタリング処理を書けるのがawkの特長です。
基本的な使い方
例えば以下のようなテキストファイルがあるとします。
sample1.txt
hoge fuga foo bar
とりあえず、sample.txtからfugaを取り出してみます。
awk '{print $2}' sample1.txt // fuga
このコマンドでスペース区切りの2番目の要素を取り出すことができます。
他にも色々できます。例えば正規表現を使ってみます。
まずこんなテキストファイルがあるとします。
sample2.txt
hoge fuga hello world test dayo
この中からhが含まれる行だけを取り出してみます。
awk 'match($0, /h.*/)' sample2.txt // hoge fuga hello world
第1引数に$0を指定していますが、これで全要素を指定することができます。
第2引数は見ての通りhから始まる要素を取り出す正規表現です(hは途中でもOKです)。
awkの使い方は他にも色々あるのですが、キリがないのでこの記事では割愛します。
ログから会員番号を抽出してみる
どのようなデータをログに残しているかはシステムやサービスによって当然異なるとは思うのですが、ログをちょっと眺めてawkコマンドを活用すれば、膨大なログの中から必要な情報を抜き出すことができます。
自分の場合、障害にかかって画面を表示できなかったサイト会員がどれくらいいるのか調べる必要がありました。
出力されていたエラーログは大体こんな感じでした。
sample_error.log
ERROR~~~~~~(中略) /error/no/genninn.jspが存在しません。 ~~~(中略)~~~memberCode=213122~~~(中略)
だいぶ端折ってしまいましたが、こんなログ大量に出力されていました。
この中には今回の障害には関係ないものも含まれているので、今回の障害に関連したものだけを抽出してみます。
grep ERROR sample_error.log | grep genninn.jsp | awk '{print $15}' | sort | uniq ///memberCode=111112 memberCode=111133...
awkも他のコマンド同様、パイプで繋いで使うことができます。
まず最初にgrepコマンドで対象ファイルの中で「ERROR」を含む行を取得。さらに対象ファイルの名前を含む行を抽出します。ここでようやくawkが登場。各行の中からmemberCodeを含む要素を抽出しています(memberCodeはスペース区切りで15番目でした)。
sortは文字通りのソート、繰り返しエラーにはまっている会員の重複を排除するのにuniqを使っています。
当時の稼働系サーバーは一桁の台数だったので、各サーバーに入って同じコマンドを叩き、出てきたものをsort|uniqしてまとめました。
ここでさらにawkを活用してやれば「memberCode=」の部分を削るなんてこともできそうですね。
結果…
実に100以上の会員がgenninn.jspを表示できずに困っていたことが判明しました。
我ながら本当に酷いですね…
悔い改めつつ今日はこんなところで。