Log4j の DailyRollingFileAppender を使用したログローテートが変。

現象

Log4j の DailyRollingFileAppender を使用したログ出力において、前日のログファイルに対してログが出力される。

例えば 2004-03-15 に起動された場合、ログファイル hoge.log に出力される。

$ ls -l hoge*
 -rwx------  1 any   hoge  37683 Mar 15 18:30 hoge.log

日付が変わり、2004-03-16 になると 前日のログがバックアップされる。

$ ls -l hoge*
 -rwx------ 1 any hoge  37683 Mar 16 00:00 hoge.log.2004-03-15  <-- バックアップされた。
 -rwx------ 1 any hoge      0 Mar 16 00:00 hoge.log             <-- 以降はこちらに出力されるはず。

以降のログは hoge.log に出力されるはずなのに、なぜか hoge.log.2004-03-15 にも出力されてしまう。

$ ls -l hoge*
 -rwx------ 1 any hoge 193423 Mar 16 01:12 hoge.log.2004-03-15 <-- なぜかここに出力される。
 -rwx------ 1 any hoge  83433 Mar 16 01:03 hoge.log            <-- こっちにもすこし出力されている。

環境

solaris
j2sdk1.4.2_02
log4j-1.2.8
jakarta-tomcat-4.1.29-LE-jdk14

調査

単体試験で以下のようなテストを行った。

  1. テストAPを起動、複数スレッドよりログを出力しまくる。
  2. date コマンドにより時間を調整、システム上の日付を変更する。

スレッド数に関係なく、正常にログが出力されることを確認。

次に複数プロセスによる実行を行ってみた。

  1. テストAPを同時に2つ起動、複数スレッドよりログを出力しまくる。
  2. date コマンドにより時間を調整、システム上の日付を変更する。

今回の障害と同じような現象が発生した。

考察

複数プロセスがログを出力する場合はここにあるように
SocketAppender
を使用すれば解決できるとなっている。
なので、上記の障害も同様の方法で解決できそう。

ただ何故 Tomcat でこの障害が発生するのかは不明。
複数コンテキストが存在し、同じログファイルに対してログ出力した場合は複数のClassLoader毎にファイルをオープンし、複数プロセスの書き込みと同じ現象がが発生するのはわかるけど、今回は1つしかコンテキストをデプロイしていない。

ためしに ClassLoader のテストを行うため、Contextの WEB-INF/lib 配下に配置していた log4j-1.2.8 を CATAINA_HOME 配下の shared/lib に移動してみた。

WEB-INF/lib/log4j-1.2.8.jar   --->  $CATALINA_HOME/shared/lib/log4j-1.2.8.jar

動かしてみたところ正常にログローテートされた。

追加

webapps を使用した apache + tomcat 連携を行っているのだけれど、apache 経由でアクセスする場合とtomcatでアクセスする場合のコンテキストがそれぞれ別に初期化されていた。
(HttpServlet の initメソッドがTomcat起動時とApache経由のアクセス時とで2回呼ばれていた)
その結果、server.xml上のコンテキストは1つなのにもかかわらず、複数コンテキストがデプロイされているのと同じ状態になっているみたい。