雰囲気でわかる“ログローテーション”の仕組み

最近、ログまわりの設計をやっている*1。「どんなログが何のために必要なのか」という要件と、「プロダクトがどんなログを出力するか(どんな出力方式が設定できるか)」を検討し、よい落とし所を見つける、、そんな感じの作業だ。システム全体となると、機器やソフトウェアの数が多くって、ログ出力内容とログ管理(ローテーション、バックアップ、削除)まわりの検討が、(ゼロから徒手空拳で実施すると)やたらと面倒になる。「全部デフォルトの設定で、障害対応くらいできますよ」って言いたいところだが、ログ出力要件とログ管理要件が満たせていることは説明できなければならない*2。適当に流してドキュメントレビューで突っ込まれまくるくらいなら、それなりに精緻に設計していた方が楽だ*3。おっと、愚痴っぽくなってきてしまった。


さて、今日は「ログローテーションの仕組み(というか“方式”なのだが)」について、大きく3つに分類できるのではないかと思って、まとめてみた。

1) そもそもローテーションの機能がある

プロダクトにローテーションの機能があって、柔軟に設定できれば、それで終わり。ファイルつかみっぱなしでログ出力する奴(サーバプロダクト)は、柔軟に設定できるローテーションの仕組みを持っていてほしい。たいていのプロダクトには、このような仕組みがある。例は何でもよかったのだが、JBoss ASで、log4jを使ってログローテーションさせている概念図を示す。
楕円が“プロセス”で、プロセス内にある楕円が“機能”のようなイメージ。あと、ローテーションの機能を持つ楕円を灰色にしている。

2) ローテーションの機能がある奴にわたす

Apache HTTP Serverのログローテーションは、付属のrotatelogsを用いることが多い。rotatelogsは単独でも利用可能であり、次の図のように、パイプで受け取ったメッセージをログに出力する(で、もちろんローテーションもしてくれる)。


ちょっと話がずれるかもだが、バッチのアプリケーションを作成する時には、どうやってログを出力させようか悩むことがある。ログのファイル名に、起動時刻(年から秒まで)とプロセスIDを入れておいてあげると、ファイル名が重複しないので、問題は起きない*4。でも、これだとログファイルが大変な数できて、管理とか確認とか面倒すぎる。
で、Javaバッチでよくやったのが、次のようなログサーバ(log4jの機能にあるSimpleSocketServer)を起動し、バッチアプリケーションは、そこに向かってログを出力する方式*5

これなら同時にいくつアプリケーションが起動しようと、エラーになることはない。ログ管理の設定も、ログサーバの設定に集約される。

3) 外からローテーションする

典型例がlogrotate。とても有名なlogrotateだが、cronから起動されて、ログのリネームをするプログラム。ログを切りかえる時に、syslogdにハングアップのシグナル(SIGHUP)を送る。syslogdは、SIGHUPをキャッチして、ログを再オープンするようになっている(っぽい)ので、ローテーションができる。当たり前だが、外から何らかの信号をキャッチできるような仕組みがなければ、この方式は成り立たない。


logrotate以外にも、ログ管理に関するコマンドが用意されているサーバプロダクトも存在する*6。ローテーションは、スクリプトで作り込めってことね。でもコマンドは用意してね。

2011/11/09追記

ちなみに、サーバプロセスがログファイルをつかみっぱなしで、上記のいずれの方式でもローテーションできない場合には、次のいずれかの方法しかないよね。

  • UNIX/Linuxの場合であれば、ログファイルをコピーし、クリアする。ただし、コピーとクリアの間に(たまたま)出力されたログはロストする。Windowsの場合には、2プロセスが同時にファイルをオープンすることはできないので、次のプロセス停止しかない
  • サーバプロセスを停止し、ローテーションし、サーバプロセスを起動する

*1:もちろん、他にもやっているが。さぼりさぼり。

*2:とにかく締め切りに追われて追われて、バタバタしながら「えいやっ」で書き上げクローズした、そんな要件定義のドキュメントに、ばっちり書いてあるのだ。

*3:管理をゆるくする設計は、しっかり理屈と根拠で理論武装するのが大変だが、管理をきつくする設計は、ゆるい論理で(頭使わずに)筋が通るので、どうしても後者に流れがちになってしまう。人って。。

*4:起動時刻だけでは、同時に2つのバッチプログラムが起動した時に、同じファイルをオープンしにいってしまう。Windows系のOSであれば、一発でエラー。

*5:SyslogAppenderを使って、syslogdに出力してもよい。

*6:SIGHUPよりは安心感がある。