アクセスログから指定範囲のIPアドレスを含む行を抜き出す
アクセスログから、指定範囲のIPアドレスを含む行を抜き出す。ログはまあまあのファイルサイズがあり、処理はできるだけ速く完了したい。そこで、幾つかの方法を試してみた。
例として、Webサーバのhttpdアクセスログを使う。ログのサイズは約19MBで、72733行ある。IPアドレスの範囲はCIDRで記述する。ここでは、抜き出すIPアドレスの範囲として、東京大学のIPアドレスを用いる。https://www.nc.u-tokyo.ac.jp/riyou/192.51.htmlによれば、IPアドレス範囲は130.69.0.0/16
、133.11.0.0/16
、157.82.0.0/16
である。
比較
$ wc -l /var/log/lighttpd/access.log* 4141 /var/log/lighttpd/access.log 4688 /var/log/lighttpd/access.log.1 5019 /var/log/lighttpd/access.log.10 6265 /var/log/lighttpd/access.log.11 8291 /var/log/lighttpd/access.log.12 5657 /var/log/lighttpd/access.log.2 4850 /var/log/lighttpd/access.log.3 4626 /var/log/lighttpd/access.log.4 4963 /var/log/lighttpd/access.log.5 6795 /var/log/lighttpd/access.log.6 4580 /var/log/lighttpd/access.log.7 5804 /var/log/lighttpd/access.log.8 7054 /var/log/lighttpd/access.log.9 72733 total
$ time cat /var/log/lighttpd/access.log* | perl ipfilter.pl | wc -l 612 real 0m2.355s user 0m2.306s sys 0m0.036s $ time cat /var/log/lighttpd/access.log* | python ipfilter_ipcalc.py | wc -l 612 real 0m6.868s user 0m6.782s sys 0m0.077s $ time cat /var/log/lighttpd/access.log* | python ipfilter_netaddr.py | wc -l 612 real 0m3.932s user 0m3.861s sys 0m0.062s $ time cat /var/log/lighttpd/access.log* | runhaskell ipfilter.hs | wc -l 612 real 0m3.706s user 0m3.599s sys 0m0.101s
ipcalc/Pythonが最も遅い。どうやら、IPアドレス範囲に含まれているかのチェック:ipcalc.Network.in_network(other)
で、long(address)
を何度も呼び出しているせいのようだ。
iproute/HaskellはIPアドレス群の管理にTRIEを使っており、そこそこ早い。コンパイルしたらもっと速くなるかもしれない。