一文字パッチでlogmonをログローテートに対応させる

ログを監視する仕組みについて調べていたらlogmonというツールを見つけた。IBM製ってとこに違和感があるけどシンプルな作りなのでインストールも楽で使いやすいらしい。1枚のスクリプトでしかも唯一読めるPerlだったのでどんなことをしているのかチラ見してみた。

おおまかな流れ

  1. confからログのpath、検知する文字列、検知時のアクションを読みこむ
  2. ログファイルの数分forkしてtailの標準出力をファイルハンドルへ流す
  3. 流れてくる1行1行にマッチ演算子で検出する文字列を引っかける
  4. 引っかかったらアクションを実行

本当にシンプルだった!でも確かにこれだけでもログ監視として機能する。


で、一点気になったのが公式のページにも書いてあるこれ

■ ログファイルの回転について

logrotate などで監視対象のログファイルが新規作成された場合は、次のコマンドで、監視するファイルを新規ファイルに切り替える必要があります。
# /etc/init.d/logmon switch

下記の例のように、logrotate の設定ファイル内の監視対象ログファイルの postrotate エントリーに、このコマンドを記載しておいてください。

http://www-06.ibm.com/jp/domino01/mkt/cnpages7.nsf/page/default-00057580


ログファイルの回転って言葉もおかしいけど、ローテートに対応してないとかもっと頑張れなかったのかよ!と思って見てみるとこんなコードだった。

open ( IN, "tail -n$tail_num -f $target|" );

あれ。これ-Fにしたらswitch打たなくて済むんじゃね?と思ったので実際に試してみた。

tailのオプションを-fから-Fに変更 (一文字パッチ)

@@ -79,7 +79,7 @@
     unless ( fork() ) {      # Child
         $SIG{HUP}  = \&catch_hup;
         $SIG{TERM} = \&catch_term;
-        open ( IN, "tail -n$tail_num -f $target|" );
+        open ( IN, "tail -n$tail_num -F $target|" );
         while ( <IN> ) {
             foreach $message ( keys %{$Config{$target}} ) {
                 if ( $_ =~ m/$message/ ) {

UAがlibwww-perlなアクセスがあったときはdateをログに吐くようにする

$ cat logmon.conf
# Monitor for messages
:/var/log/httpd/access_log
(libwww-perl)
date >> /tmp/logmon.log

logmon.pl を実行

$ sudo ./logmon.pl -f logmon.conf

1秒ごとGETしてログを伸ばす。

$ while true ; do GET localhost > /dev/null ; sleep 1 ; done

このGETコマンドはlwpでアクセスするので logmon に引っかかって /tmp/logmon.log にも1秒ごとにdateが記録される。

logrotateを実行してログファイルを切り替える

$ sudo logrotate /etc/logrotate.conf

すると

tail: `/var/log/httpd/access_log' has become inaccessible: No such file or directory
tail: `/var/log/httpd/access_log' has appeared;  following end of new file

やっぱりちゃんと見つけてくれた!もちろん /tmp/logmon.log を見てもログは途切れていない。


ちなみに今回試した環境はCentOS 6.0だけどmanを見ると最近のBSD系なら問題なく動きそうな気がする。(古いFreeBSDとかだとこのオプションが無いらしい)

CentOSGNU tail

       -F    same as --follow=name --retry
       --retry
              keep trying to open a file even when it is or becomes inaccessible; useful when following by name,
              i.e., with --follow=name

OSXのBSD tail

       -F     The -F option implies the -f option, but tail will also check to see if the file being followed has been renamed or rotated.  
                The file is closed and reopened when tail detects that the filename being read from has a new inode number.
                The -F option is ignored if reading from standard input rather than a file.


Linuxで使われることが前提で書かれているのに tail -F にしていないのは何か他に理由があるんだろうか。