Webアプリケーションのログを、logrotateで一律ローテーションさせたい、という話をときどき聞きます。
log4jのローテーションを外部から指示する術は、ExternallyRolledFileAppenderを使えば可能です。
<appender name="file" class="org.apache.log4j.varia.ExternallyRolledFileAppender">
<param name="file" value="application.log" />
<param name="threshold" value="INFO"/>
<param name="port" value="9000"/>
<param name="append" value="true" />
</appender>
org.apache.log4j.varia.Roller を使ってローテーション指示を送ることができますが、ローテーションファイルが*.1が自動で作られてしまい、うまくありません。
そこで、他のログローテーショナブルなプロセスたちと同じように、SIGHUPを受け取ったらファイルを一度クローズし、再度開き直すようにしてみます。
public class LogRotatableFileAppender extends FileAppender {
public LogRotatableFileAppender() {
Signal.handle(new Signal("HUP"), new SignalHandler() {
@Override
public void handle(Signal signal) {
closeFile();
activateOptions();
}
});
}
}
これで、例えばTomcatで動いているアプリケーションの場合、以下のようにlogrotate.conf
にpostrotateでSIGHUPをtomcatプロセスに送るようにすれば、logrotateで設定にしたがい、ローテーションされるようになります。
logrotate.conf
/var/log/app.log
{
rotate 6
size=100k
missingok
daily
sharedscripts
postrotate
/bin/kill -HUP `cat /var/run/tomcat.pid 2>/dev/null` 2> /dev/null
endscript
}