labunix's blog

labunixのラボUnix

アクセスログからワンライナーで接続元毎、閲覧先毎の接続回数の集計をしてみる。

■アクセスログからワンライナーで接続元毎、閲覧先毎の接続回数の集計をしてみる。

■まずはプロキシのログから。
 環境は以下。

$ lsb_release -d
Description:	Debian GNU/Linux 7.9 (wheezy)

■条件1
 対象は非圧縮の「access.log*」とする。
 ※「zcat」と混ぜるのも面倒なので。
  もっとあるなら、例1のように並べても良いし、
  同フォルダに他に無いなら、例2でも良い。

  例1「/var/log/squid/access.lo{g,g.1,g.2,g.3}」
  例2「/var/log/squid/access.log*」

$ sudo du -h /var/log/squid/access.lo{g,g.1}
920K	/var/log/squid/access.log
4.8M	/var/log/squid/access.log.1

■条件2
 ログのフォーマットは以下とする。

$ sudo grep ^logformat /etc/squid/squid.conf 
logformat combined %>a %ui %un [%tl] "%rm %ru HTTP/%rv" %Hs %<st "%{Referer}>h" "%{User-Agent}>h" %Ss:%Sh

■条件3
 閲覧の定義はメソッドが「GET」と「CONNECT」で、
 ステータスが「 200 」のものとする。
 例えば、「HEAD」や「POST」や「OPTIONS」、
 「PUT」、「DELETE」等は含まない。
 また、バイト数がたまたま「 200 」だとしても誤差の範囲として無視する。

$ sudo cat /var/log/squid/access.lo{g,g.1} | \
    awk -F\" '{print $2}' | awk '{print $1}' | \
    sort | uniq -c | sort -nr
  18039 GET
   2524 CONNECT
    454 POST
      2 OPTIONS
      1 HEAD

■接続元IPをカウントし、
 合計で100回以上アクセスしているIPのみアクセスが多い順に表示する。
 ※以下は下位プロキシサーバのIPなのであまり面白くない。

$ sudo cat /var/log/squid/access.lo{g,g.1} | \
    awk '/\"GET .*\" 200 / || /\"CONNECT .*\" 200 / \
         {cnt[$1]+=1};END{for (key in cnt) \
                         {if(cnt[key] > 100) \
                         {print cnt[key],key}}}' | \
    sort -nr
17175 XXX.XXX.XXX.XXX
  102 YYY.YYY.YYY.YYY

■リファラなしの閲覧先ドメインをカウントし、
 合計で100回以上アクセスがあるURLのみアクセスが多い順に表示する。
 
$ sudo cat /var/log/squid/access.lo{g,g.1} | \
    awk -F\" '/GET .* 200 / || /CONNECT .* 200 / \
              {cnt[$2]+=1};END{for (key in cnt) \
                              {if(cnt[key] > 100) \
                              {print cnt[key],key}}}' | \
    sed -e 's% HTTP/...%%g' | sort -nr
317 GET http://api.b.st-hatena.com/entry.count?
187 CONNECT pbs.twimg.com:443
171 GET http://sankei2ad.durasite.net/A-affiliate2/mobile?
159 GET http://dlv.itmedia.jp/adsv/v1?
145 GET http://graph.facebook.com/?
142 GET http://www.google-analytics.com/ga.js
140 GET http://b.hatena.ne.jp/labunix/search.data?
139 GET http://www.google-analytics.com/analytics.js
136 GET http://b.hatena.ne.jp/my.entry?
107 GET http://cdn.api.b.hatena.ne.jp/entry/button/?

■上記はどれも一瞬で終わってしまってつまらないので、
 約160MBのサンプルをダウンロードする。

 NASA-HTTP
 http://ita.ee.lbl.gov/html/contrib/NASA-HTTP.html

$ wget ftp://ita.ee.lbl.gov/traces/NASA_access_log_Aug95.gz
$ gzip -l NASA_access_log_Aug95.gz 
         compressed        uncompressed  ratio uncompressed_name
           16633316           167813770  90.1% NASA_access_log_Aug95
$ gzip -l NASA_access_log_Aug95.gz  | \
    awk '(NR>1){print $2/1024/1024"MB"}'
160.04MB

■今回はgzip圧縮なので、zcatに変更。

$ echo "フォーマットサンプル";zcat NASA_access_log_Aug95.gz | head -1
フォーマットサンプル
in24.inetnebr.com - - [01/Aug/1995:00:00:01 -0400] "GET /shuttle/missions/sts-68/news/sts-68-mcc-05.txt HTTP/1.0" 200 1839

■メソッドチェック。
 今回は100以上の条件を付けたが、
 数件のログが壊れている気がするが、誤差の範囲としてスルーする。
 
$ zcat NASA_access_log_Aug95.gz | nkf -Lu -d | \
    awk -F\" '{print $2}' | awk '{print $1}' | \
    sort | uniq -c | sort -nr | awk '($1>100){print}'
1565812 GET
   3965 HEAD
    111 POST

■条件にトップ10を追加して接続元毎の接続回数の集計

$ zcat NASA_access_log_Aug95.gz | \
    awk '/\"GET .*\" 200 / || /\"CONNECT .*\" 200 / \
         {cnt[$1]+=1};END{for (key in cnt) \
                         {if(cnt[key] > 100) \
                         {print cnt[key],key}}}' | sort -nr | head -10
6469 edams.ksc.nasa.gov
4632 piweba4y.prodigy.com
4403 piweba5y.prodigy.com
4227 piweba3y.prodigy.com
3758 163.206.89.4
3180 news.ti.com
2989 intgate.raleigh.ibm.com
2952 mpngate1.ny.us.ibm.net
2874 e659229.boeing.com
2744 webgate1.mot.com

■条件にトップ10を追加して閲覧先毎の接続回数の集計

$ zcat NASA_access_log_Aug95.gz | \
   awk -F\" '/GET .* 200 / || /CONNECT .* 200 / \
              {cnt[$2]+=1};END{for (key in cnt) \
                              {if(cnt[key] > 100) \
                              {print cnt[key],key}}}' | \
   sed -e 's% HTTP/...%%g' | sort -nr | head -10
77769 GET /images/NASA-logosmall.gif
63804 GET /images/KSC-logosmall.gif
58349 GET /images/MOSAIC-logosmall.gif
58029 GET /images/USA-logosmall.gif
57615 GET /images/WORLD-logosmall.gif
54571 GET /images/ksclogo-medium.gif
41099 GET /ksc.html
33393 GET /history/apollo/images/apollo-logo1.gif
30881 GET /images/launch-logo.gif
26245 GET /

■ちなみに私の環境では約10秒以内に結果が出る。

$ time zcat NASA_access_log_Aug95.gz | \
    awk '/\"GET .*\" 200 / || /\"CONNECT .*\" 200 / \
         {cnt[$1]+=1};END{for (key in cnt) \
                         {if(cnt[key] > 100) \
                         {print cnt[key],key}}}' | sort -nr | head -10
6469 edams.ksc.nasa.gov
4632 piweba4y.prodigy.com
4403 piweba5y.prodigy.com
4227 piweba3y.prodigy.com
3758 163.206.89.4
3180 news.ti.com
2989 intgate.raleigh.ibm.com
2952 mpngate1.ny.us.ibm.net
2874 e659229.boeing.com
2744 webgate1.mot.com

real	0m3.357s
user	0m3.132s
sys	0m0.212s

$ time zcat NASA_access_log_Aug95.gz | \
   awk -F\" '/GET .* 200 / || /CONNECT .* 200 / \
              {cnt[$2]+=1};END{for (key in cnt) \
                              {if(cnt[key] > 100) \
                              {print cnt[key],key}}}' | \
   sed -e 's% HTTP/...%%g' | sort -nr | head -10
77769 GET /images/NASA-logosmall.gif
63804 GET /images/KSC-logosmall.gif
58349 GET /images/MOSAIC-logosmall.gif
58029 GET /images/USA-logosmall.gif
57615 GET /images/WORLD-logosmall.gif
54571 GET /images/ksclogo-medium.gif
41099 GET /ksc.html
33393 GET /history/apollo/images/apollo-logo1.gif
30881 GET /images/launch-logo.gif
26245 GET /

real	0m9.808s
user	0m9.557s
sys	0m0.228s