プロセス置換を使ってjsvcの標準出力をローテートする。

jsvcの起動オプションの-outfile/-errfileにファイルパスを指定すると、そのファイルに標準出力/標準エラー出力を吐きだすようになる。但しこのファイルは普通にはローテートされないので、何らかの方法でローテートするようにしたい。

例としてTomcat6以降 + jsvcを使っている場合を考える。標準的な起動スクリプトだと下のようになっていると思う。
cf: http://svn.apache.org/repos/asf/tomcat/tc7.0.x/trunk/bin/daemon.sh

#!/bin/sh
...
test ".$CATALINA_OUT" = . && CATALINA_OUT="$CATALINA_BASE/logs/catalina-daemon.out"
...
    start   )
      "$JSVC" $JSVC_OPTS \
      -java-home "$JAVA_HOME" \
      -user $TOMCAT_USER \
      -pidfile "$CATALINA_PID" \
      -wait "$SERVICE_START_WAIT_TIME" \
      -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 $?
    ;;
...

これだと「catalina-daemon.out」がどんどん肥大化していくので、これをローテートさせたい。

ググると、logrotateでファイルを移動しKILL -HUPする方法や、mkfifoで作ったファイルをoutfileに指定しつつそれを読み出してrotatelogsに渡す方法があったけど、BashのProcess Substitutionを使えばいいような気がしてやってみたら出来たと思う。


cf: bashのプロセス置換機能を活用して、シェル作業やスクリプト書きを効率化する - 双六工場日誌


まずこれはbashの機能なので起動スクリプトshebangの指定をbashに変える。
それで、jsvcを起動する前に標準出力をrotatelogsへの入力に切り替えてやる。

#!/bin/bash
...
test ".$CATALINA_OUT" = . && CATALINA_OUT="$CATALINA_BASE/logs/catalina-daemon.out"
...
    start   )
      exec 3>&1
      exec 4>&2
      exec 1> >(/usr/local/apache2/bin/rotatelogs "${CATALINA_OUT}.%Y%m%d" 86400 540) 2>&1

      "$JSVC" $JSVC_OPTS \
      -java-home "$JAVA_HOME" \
      -user $TOMCAT_USER \
      -pidfile "$CATALINA_PID" \
      -wait "$SERVICE_START_WAIT_TIME" \
      -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

      STATUS=$?
      exec 1>&3
      exec 2>&4
      exit $STATUS
    ;;
...

一応元の標準出力らを別のファイルディスクリプタに逃がしておいてあとで戻すようにしている。
Process Substitutionは実体はnamed pipesらしいですがmkfifoするより速いし手軽だしってWikipediaに書いてあった