• JSVCのログローテート

    2013年07月24日 21時30分
    JSVC利用時のログローテートについて色々調べたのでメモっておきます。
    なお、Linux上でのJSVC 1.0.15の内容です。


    rotatelogsで行けるか


    JSVCの起動スクリプトはこのような感じです。
    start   )
          "$JSVC" $JSVC_OPTS \
          -java-home "$JAVA_HOME" \
          -user $TOMCAT_USER \
          -pidfile "$CATALINA_PID" \
          -wait 10 \
          -outfile "$CATALINA_OUT" \
          -errfile "&1" \
          -classpath "$CLASSPATH" \
          "$LOGGING_CONFIG" $JAVA_OPTS $CATALINA_OPTS \
          -Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" \
          -Dcatalina.base="$CATALINA_BASE" \
          -Dcatalina.home="$CATALINA_HOME" \
          -Djava.io.tmpdir="$CATALINA_TMP" \
          $CATALINA_MAIN
          exit $?
        ;;


    ログ出力を指定するオプションはoutfileerrfileの2つで
    名前の通り標準出力と標準エラー出力の出力先を指定します。

    最初はここにrotatelogsを指定してみました。
    -outfile "|/usr/local/apache2/bin/rotatelogs $CATALINA_OUT.%Y%m%d 86400 540" \

    しかし、そんなに便利には出来ていません。


    調べたところこれらのオプションに指定できる値は次の通りです。
    • &1 (標準出力)
    • &2 (標準エラー出力)
    • SYSLOG (SYSLOG)
    • ファイルパス

    ならば一旦全部標準出力に出してパイプに流してみる。
    start   )
          "$JSVC" $JSVC_OPTS \
          -java-home "$JAVA_HOME" \
          -user $TOMCAT_USER \
          -pidfile "$CATALINA_PID" \
          -wait 10 \
          -outfile "&1" \
          -errfile "&1" \
          -classpath "$CLASSPATH" \
          "$LOGGING_CONFIG" $JAVA_OPTS $CATALINA_OPTS \
          -Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" \
          -Dcatalina.base="$CATALINA_BASE" \
          -Dcatalina.home="$CATALINA_HOME" \
          -Djava.io.tmpdir="$CATALINA_TMP" \
          $CATALINA_MAIN |/usr/local/apache2/bin/rotatelogs $CATALINA_OUT.%Y%m%d 86400 540
          exit $?
        ;;


    ダメ。JSVCがdaemon化されるためかうまく取れません。
    (試したところ親プロセスの出力がコンソールに出て子プロセスの出力がパイプに流れる。
    この辺りのdaemonの動作をちゃんと知ってればやり方があるのかも。)

    rotatelogsはちょっと無理そう。


    logrotate + SIGHUP


    ならば仕方ないlogrotateで行きます。

    簡単に行くならcopytruncateを指定して終わりなのですが、
    copyとtruncate処理が気持ち高コストな気がしたり、
    copyとtruncateの間のログが欠損する確率がわずかながら有る等
    若干もやっとするので使わなくて済むか調べます。


    copytruncateを指定しない場合にはログファイルの再オープンが必要になり、
    一般的にはSIGHUPを送ることで行われます。

    しかし、JSVCの場合は以下のような動作になっており、SIGHUPを送っても再オープンされません。
    1. 親プロセスでファイルをオープン
    2. 子プロセスを起動 (子プロセス側で再オープンしないので親プロセスと同じファイルを使用)
    3. SIGHUP
    4. 子プロセス再起動

    (まあ仮に子プロセス再起動時にファイルを再オープンしてくれたとしても
    プロセス再起動自体がちょっとまずいのでどの道却下なのですが・・・)


    logrotate + SIGUSR1


    ファイルオープン周りのソースをさらに読み進めたところ、SIGUSR1というのが実装されています。

    SIGUSR1を送ると次のような動作になります。
    1. 親プロセスでファイルをオープン
    2. 子プロセスを起動 (子プロセス側で再オープンしないので親プロセスと同じファイルを使用)
    3. SIGUSR1
    4. 子プロセスのファイルを再オープン

    子プロセスはファイルの再オープンのみを行ってくれるという望み通りの結果ですが、
    親プロセスは再オープンされず残ってしまいます。

    親プロセスのSIGUSR1にファイルの再オープン処理を追加すれば解決するような気もするのですが
    前述の通りdaemonの動作に明るくなく、危険な気がしたのでやめておきました。


    結局logrotate + copytruncate


    JSVCのログは量も少ないし欠損して困るデータも無いよねと自分に言い聞かせ
    最終的にlogrotate + copytruncateで行くことにしました。

    色々調べるのが大変だったわりには実に普通な結果です。

    コメントを書く

    名前
    本文
    編集用パスワード
    管理者のみ閲覧