- Linux Shell和基本指令
- Bash shell语法
- 正则表达式
- 文本处理之grep
- 文本处理之sed
- 文本处理之awk
- Text GUI编程
- Tomcat启动脚本分析
- gradlew脚本分析
前言
不仅要知道如何启动、关闭tomcat,还要知道tomcat的启动脚本都做了些什么事情。
这篇只针对linux下,window下的逻辑也大同小异,只是语法上的差别。
在此之前,我们需要知道如何根据指定的Main Class启动一个jar,通常Main Class都是在jar中的的清单文件中配置,然后通过java -jar xx.jar启动,但有时候也可以通过java -classpath ./xx.jar com.xx.Main在后面指定一个Main Class,而tomcat就是这种方式做的。
tomcat中的Main Class在bin/bootstrap.jar的org.apache.catalina.startup.Bootstrap下,启动过程则是收集一些必要参数,然后传递给Main函数和JVM。
启动过程
startup.sh
这个脚本并不是启动过程的关键,在这个脚本中,做的事情不多,主要是获取到catalina.sh脚本的相对路径并调用,比如startup.sh在bin目录下,你在终端中进入这个bin,然后执行./startup.sh,那么其中有个参数PRGDIR则是./,如果你在上一层执行,如./bin/startup.sh,那么PRGDI将会是./bin,然后PRGDI会拼接上catalina.sh,然后调用,如下。
exec "$PRGDIR"/"$EXECUTABLE" start "$@"
start和$@是参数,$@表示传入脚本的所有参数。
catalina.sh
shutdown.sh和startup.sh都会调用 catalina.sh处理,只是参数不同,startup.sh的话第一个参数为start。
系统检测
下面这段是检测操作系统的,他会根据所在系统,做一些针对特定系统的逻辑,不需要关心。
cygwin=false
darwin=false
os400=false
hpux=false
case "`uname`" in
CYGWIN*) cygwin=true;;
Darwin*) darwin=true;;
OS400*) os400=true;;
HP-UX*) hpux=true;;
esac
设置CATALINA_HOME、CATALINA_BASE
设置CATALINA_HOME和CATALINA_BASE变量值
[ -z "$CATALINA_HOME" ] && CATALINA_HOME=`cd "$PRGDIR/.." >/dev/null; pwd`
[ -z "$CATALINA_BASE" ] && CATALINA_BASE="$CATALINA_HOME"
调用setenv设置变量
调用setenv.sh设置变量,这个文件是留给我们自定义环境变量的,比如设置JAVA_HOME,他默认不存在,需要我们手动创建。
if [ -r "$CATALINA_BASE/bin/setenv.sh" ]; then
. "$CATALINA_BASE/bin/setenv.sh"
elif [ -r "$CATALINA_HOME/bin/setenv.sh" ]; then
. "$CATALINA_HOME/bin/setenv.sh"
fi
可以在其中设置JAVA_HOME,可以供我们设置的变量名在catalina.sh的开头已经全部列举出来了,这里就不说了。
export JAVA_HOME=/usr/lib/jvm/java-11
获取java路径
还有一个脚本setclasspath.sh用来设置_RUNJAVA变量,他存储着java的执行路径。
if [ -r "$CATALINA_HOME"/bin/setclasspath.sh ]; then
. "$CATALINA_HOME"/bin/setclasspath.sh
获取到bootstrap路径
CLASSPATH="$CLASSPATH""$CATALINA_HOME"/bin/bootstrap.jar
run启动
一般都是通过./startup.sh启动,但是关闭时候需要通过shutdown.sh关闭,如果我们想在终端运行后通过Ctrl+C这种方式随时关闭,可以执行./catalina.sh run,而他最终会执行下面这条命令。
eval exec "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER "$JAVA_OPTS" "$CATALINA_OPTS" \
-D$ENDORSED_PROP="\"$JAVA_ENDORSED_DIRS\"" \
-classpath "\"$CLASSPATH\"" \
-Dcatalina.base="\"$CATALINA_BASE\"" \
-Dcatalina.home="\"$CATALINA_HOME\"" \
-Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
org.apache.catalina.startup.Bootstrap "$@" start
_RUNJAVA变量是Java的路径,而后面一些是参数,如日志配置,类路径,最后一个 org.apache.catalina.startup.Bootstrap表示运行的主函数所在类,以及传递给主函数的参数。
start启动
如果参数是start,那么表示后台运行,那么需要在命令前面加nohup,以及在命令后面加&,这种方式在linux中表示让程序在后台运行。
eval $_NOHUP "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER "$JAVA_OPTS" "$CATALINA_OPTS" \
-D$ENDORSED_PROP="\"$JAVA_ENDORSED_DIRS\"" \
-classpath "\"$CLASSPATH\"" \
-Dcatalina.base="\"$CATALINA_BASE\"" \
-Dcatalina.home="\"$CATALINA_HOME\"" \
-Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
org.apache.catalina.startup.Bootstrap "$@" start \
>> "$CATALINA_OUT" 2>&1 "&"
stop终止
tomcat终止的办法是通过一个Socket监听,如果接收到SHUTDOWN字符的话,那么则退出,还有是在start启动后,如果配置了pid文件,则向这个pid文件写入tomcat的进程id,在执行stop命令时,会通过kill -0先检测进程是否正常。
eval "\"$_RUNJAVA\"" $LOGGING_MANAGER "$JAVA_OPTS" \
-D$ENDORSED_PROP="\"$JAVA_ENDORSED_DIRS\"" \
-classpath "\"$CLASSPATH\"" \
-Dcatalina.base="\"$CATALINA_BASE\"" \
-Dcatalina.home="\"$CATALINA_HOME\"" \
-Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
org.apache.catalina.startup.Bootstrap "$@" stop