为了更加安全,生产环境中我更加青睐把tomcat 使用 jsvc 以守护进程的方式启动(daemon.sh )。这样tomcat自身将会生成另外一个日志文件(catalina-daemon.out),而不是之前的catalina.out。但是随之出现2个问题:1.catalina-daemon.out这个文件不会自动切割,而且会无线增大。2.catalina-daemon.out里面log输出等级无法更改,大量info信息占据了磁盘。为了针对这两个问题特意研究了一番,研究过程因功力尚浅所以并不专业,敬请谅解。
一.catalina-daemon.out自动切割问题。
第一时间看到这个问题,首先想到的是类似于nginx的log切割方法。于是从daemon.sh里找到了它输出的路径,大约在136行。
test ".$CATALINA_OUT" = . && CATALINA_OUT="$CATALINA_BASE/logs/catalina-daemon.out"
可以直接更改到我们指定的目录下,并且用时间方式命名
test ".$CATALINA_OUT" = . && CATALINA_OUT="/XXX/catalina-daemon%Y-%m-%d.out"
但是使用这种方式每次更改需要重新启动tomcat才会生效。tomcat不像nginx拥有平滑重启的功能,每次重启都需要重新加载项目会直接导致项目中断,并不适合线上环境使用,故而pass掉。
于是百度了一下,但是并没有发现太好的解决办法。网上更多的是通过通过cronlog这个工具对catalina.out这个文件进行分割,死马当活马医于是尝试了一下仿照使用,把文件更改为
test ".$CATALINA_OUT" = . && CATALINA_OUT="|/usr/local/sbin/cronolog $CATALINA_BASE/logs/catalina-daemon%Y-%m-%d.out"
但是并没有生效,不知道是不是我用错了。
又想我重新生产成一个catalina-daemon.out,把之前的mv成123.log(随便起的名,方便后面更加直观说明,语文没学好)是否可以解决这个问题?但是我发现再不重启的前提下,tomcat会持续在123.log这个文件继续输出。当时便百度了一个linux文件标示的知识,发现也仅仅有inode,并不会产生一个唯一的文件标示符。google了一下大概意思是说tomcat启动后会把这个文件直接映射到内存中,也就是tomcat启动时的虚拟机里,不是按照路径+文件名的方式进行输出。那我要直接从内存这块里修改呢?因为确实能力有限,就没有做再深入的研究。
无奈之下只能选用一个最简单暴力的方法,算是临时解决了一下问题,发现网上有就给copy过来,具体如下:
#!/bin/bash thedate=`date --rfc-3339=date` predate=`date +%Y-%m-%d --date="-7 day"` rmfile="/xxxx/server/tomcat/logs/catalina-daemon.${predate}.out" outfile="/xxxx/server/tomcat/logs/catalina-daemon.out" if [ -f ${rmfile} ];then rm -f ${rmfile} fi if [ -f ${outfile} ];then cp ${outfile} /xxxx/server/tomcat/logs/catalina-daemon.${thedate}.out echo "" > ${outfile} fi exit 0
不过这样做有可能会丢失一小部分日志,不知道有没有更好的解决办法。还看到有人用logrotate,不过这里就没有做实验。如果大家有更好的办法,欢迎指教。
二.catalina-daemon.out输出等级问题
catalina-daemon.out跟catalina.out文件一样,是存放着控制台输出的日志。但是默认情况是info级别,大量的info信息充斥着整个文件,所以我们应该把等级设置为WARNING来屏蔽掉这些输出信息。
SEVERE (highest value) >WARNING >INFO >CONFIG >FINE >FINER >FINEST (lowest value)
一说到更改log第一反应是修改tomcat conf下的logging.properties的文件,但是发现更改后并没有生效。
返回来去读了一下deamon.sh,发现下面145行,log配置文件路径:
if [ -z "$LOGGING_CONFIG" ]; then if [ -r "$CATALINA_BASE/conf/logging.properties" ]; then LOGGING_CONFIG="-Djava.util.logging.config.file=$CATALINA_BASE/conf/logging.properties" else # Bugzilla 45585 LOGGING_CONFIG="-Dnop" fi fi
以及第200行,启动配置
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 $?
发现启动的时候确实是读取了logging.properties这个文件,同时也发现了把控制台的标准输出跟错误输出一起都输出到$CATALINA_OUT下面,但是为什么更改后没有生效呢?无奈之下只能硬着头皮去看看tomcat源码。
说实话读源码真是要命,但是发现源码里有读取JDK下面的logging.properties,更改后发现无效。继续看
发现在源码里已经定了log输出等级为INFO,难道只能去修改源码重新编译tomcat才能生效么?
后来请教一位大神重新帮我解读源码,已经找到了问题所在,感谢大神小果儿。大致如下(个人理解)
首先 tomcat日志上有 目标 跟 源,同一个源可以有多个目标输出,同样多个源也可以对应一个输出。我们之前所更改的配置文件其实都生效了,只是对应的输出不对而已。在jsvc下定义的catalina-deamon.out的源是在tomcat项目(webapp)下,所以想要修改catalina-deamon.out的输出等级只需要更改项目下logging.properties文件就可以生效,如果有多个项目则需要到每个项目下修改。顺便一提。catalina.out对应的源是tomcat自身,所以更改tomcat下的配置文件就可以生效。