shellコマンドでログを統計する方法を詳しく説明します。


前言
shell命令を使うことによって、簡単にログの統計と分析ができます。サービスに異常がある場合、ログを調べる必要があります。統計日誌のスキルを身につける必要があります。
以下の内容を含むログファイルaccess.logがあると仮定します。私たちはこのファイルを統計するログを例にします。

date=2017-09-23 13:32:50 | ip=40.80.31.153 | method=GET | url=/api/foo/bar?params=something | status=200 | time=9.703 | bytes=129 | referrer="-" | user-agent="Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7" | cookie="-"
date=2017-09-23 00:00:00 | ip=100.109.222.3 | method=HEAD | url=/api/foo/healthcheck | status=200 | time=0.337 | bytes=10 | referrer="-" | user-agent="-" | cookie="-"
date=2017-09-23 13:32:50 | ip=40.80.31.153 | method=GET | url=/api/foo/bar?params=anything | status=200 | time=8.829 | bytes=466 | referrer="-" | user-agent="GuzzleHttp/6.2.0 curl/7.19.7 PHP/7.0.15" | cookie="-"
date=2017-09-23 13:32:50 | ip=40.80.31.153 | method=GET | url=/api/foo/bar?params=everything | status=200 | time=9.962 | bytes=129 | referrer="-" | user-agent="Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7" | cookie="-"
date=2017-09-23 13:32:50 | ip=40.80.31.153 | method=GET | url=/api/foo/bar?params=nothing | status=200 | time=11.822 | bytes=121 | referrer="-" | user-agent="Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7" | cookie="-"
異なるサービスに対応するログは異なるかもしれませんが、ここでは例示的なログを使用するフォーマットは以下の通りです。

date | ip | method | url | status | time | bytes | referrer | user-agent | cookie
注意:macシステムとlinuxシステムでは、命令行動が異なる場合があります。以下のコマンドは、linuxシステムで使用してください。
特殊ログを削除
統計ログの場合、私たちはHEAD要求に関心がないかもしれません。あるいはGET要求だけに関心があります。ここではまずログをフィルタする必要があります。grepコマンドを使用することができます。vは、一致するテキスト行を除外するという意味です。

grep GET access.log #     GET   
grep -v HEAD access.log #     HEAD   
grep -v 'HEAD\|POST' access.log #     HEAD   POST   
インターフェースの時間がかかります。
私たちは各行のタイムを合わせて並べ替えてもいいです。awkのmatch法を用いて正則に適合することができる。

awk '{ match($0, /time=([0-9]+\.[0-9]+)/, result); print result[1]}' access.log
awkコマンドの使い方は以下の通りです。

awk '{pattern + action}' {filenames}
私たちは実際にaction:match($0, /time=([0-9]+\.[0-9]+)/, result); print result[1] までしか使っていません。
マッチするテキスト、正規表現、結果配列が必要です。0はawkコマンド処理の各ラインを表し、結果配列は任意であり、私たちはマッチング結果を得るためにここにreult配列が入ってきて、マッチング後の結果を格納するために使用されます。
ここの正則は\dを使って数字を表していません。awk命令はデフォルトで「EREs」を使いますので、\dの表現はサポートしていません。具体的にはlinux shell正規表現(BREs、EREs、PREs)の違いを比較します。を見てください。
result配列は実際にjavascriptの結果配列と似ています。だから私たちは第二の要素、つまりマッチングした内容をプリントしました。このコマンドを実行した結果、次のようになりました。

9.703
0.337
8.829
9.962
11.822
もちろん、実際の一日の日誌は何千何万件かかもしれません。ログを並べ替えて、前の3つだけを展示する必要があります。ここではsortコマンドを使います。
ソトコマンドは、デフォルトでは小さいものから大きいものまで並べ替えられ、文字列として並べ替えられます。デフォルトでは、ソトコマンドを使うと「11」が「8」の前になります。では、-nを使って数字順に並べ替えて指定します。-rは大きいから小さい順に並べ替えて、前の3つを確認します。

awk '{ match($0, /time=([0-9]+\.[0-9]+)/, result); print result[1]}' access.log | sort -rn | head -3
結果:

11.822
9.962
9.703
最も時間がかかるインターフェースを確認します。
もちろん、私達は普通インターフェースの消耗状況を見るだけではなく、具体的な日誌もプリントアウトしなければなりません。上の命令は要求を満たすことができません。
awkの印刷はデフォルトではスペースで区切られています。つまり、2017-09-23 GETの行はawk'{print$1}'を使えば、「2017-09-23」をプリントします。同様に、$2はGETをプリントします。
ログの特徴によって、私たちは区切り記号として|を使うことができます。そうすると、それぞれの興味のある値をプリントできます。私たちは時間がかかる最高のインターフェースを探したいので、timeとdateとurlを単独で探してみます。
awkの-Fパラメータは、ユーザー定義のセパレータに使用されます。それから、次の三つの部分を数えて、それぞれ第何番目ですか?timeは第6、dateは第1、urlは第4です。

awk -F '|' '{print $6 $1 $4}' access.log
このように打てば、

 time=9.703 date=2017-09-23 13:32:50 url=/api/foo/bar?params=something
 time=0.337 date=2017-09-23 00:00:00 url=/api/foo/healthcheck
 time=8.829 date=2017-09-23 13:32:50 url=/api/foo/bar?params=anything
 time=9.962 date=2017-09-23 13:32:50 url=/api/foo/bar?params=everything
 time=11.822 date=2017-09-23 13:32:50 url=/api/foo/bar?params=nothing
私たちはtimeで並べ替えたいですが、sortは列で並べ替えられます。列はスペースで区切られています。私たちは今一番目の列はtime=xxxです。並べ替えができないので、ここでtime=を削除します。私たちは鶏のように時間を第一列に置いています。

awk -F '|' '{print $6 $1 $4}' access.log | awk -F 'time=' '{print $2}'
結果:

9.703 date=2017-09-23 13:32:50 url=/api/foo/bar?params=something
0.337 date=2017-09-23 00:00:00 url=/api/foo/healthcheck
8.829 date=2017-09-23 13:32:50 url=/api/foo/bar?params=anything
9.962 date=2017-09-23 13:32:50 url=/api/foo/bar?params=everything
11.822 date=2017-09-23 13:32:50 url=/api/foo/bar?params=nothing
sortの-kパラメータを使って並べ替えたい列を指定できます。ここで1列目です。上の並べ替えに合わせて、一番時間がかかります。

awk -F '|' '{print $6 $1 $4}' access.log | awk -F 'time=' '{print $2}' | sort -k1nr | head -3
結果:

11.822 date=2017-09-23 13:32:50 url=/api/foo/bar?params=nothing
9.962 date=2017-09-23 13:32:50 url=/api/foo/bar?params=everything
9.703 date=2017-09-23 13:32:50 url=/api/foo/bar?params=something
統計要求回数が一番多いインターフェース
どのインターフェースが毎日の要求量が一番多いかを統計する必要があるなら、uniqコマンドを新たに導入する必要があります。grep -v HEAD access.log | awk -F '|' '{print $4}' を通して、すべてのurlを選別することができます。uniqコマンドは、隣接する同じ行を削除することができます。一方、−cは、各行の出現回数を出力することができます。
だから私たちはまずurlを並べて同じurlを一緒に置いて、uniq-cを使って出現回数を統計します。

grep -v HEAD access.log | awk -F '|' '{print $4}' | sort | uniq -c
ログの数が少なすぎるので、ログに複数の項目があると仮定します。結果は以下のようになるべきです。

1 url=/api/foo/bar?params=anything
19 url=/api/foo/bar?params=everything
4 url=/api/foo/bar?params=nothing
5 url=/api/foo/bar?params=something
次はもう少しでいいです。

grep -v HEAD access.log | awk -F '|' '{print $4}' | sort | uniq -c | sort -k1nr | head -10
締め括りをつける
以上はこの文章の全部の内容です。本文の内容は皆さんの学習や仕事に一定の助けをもたらすことを望んでいます。もし疑問があれば、メッセージを残して交流してください。ありがとうございます。