windows下tomcat8启动脚本代码剖析--catalina.bat

Windows下,Tomcat可以以服务形式启动、停止,也可以执行脚本启动(startup.bat)、停止(shutdown.bat)。执行startup.bat时会调用catalina.bat,catalina.bat脚本又会调用setclasspath.bat进行java class path指定。上篇讲了startup.bat启动代码实现,本文将剖析catalina.bat的代码实现。

1、tomcat版本及安装目录

版本:8.0.36
安装目录:E:\tomcat8

2、catalina.bat代码剖析

由于catalina.bat脚本代码较多,为了讲解方便,代码说明统一采用高级语言注释//,并移除原代码中的很多rem英文注释。

@echo off  		//关闭回显
setlocal		//开启局部变量

//startup.bat调用过来第一个参数为start, 跳到mainEntry
if not ""%1"" == ""run"" goto mainEntry 	
if "%TEMP%" == "" goto mainEntry			//TEMP为空执行mainEntry,如:C:\Users\ADMINI~1\AppData\Local\Temp
if exist "%TEMP%\%~nx0.run" goto mainEntry	//%~nx为脚本文件名:catalina.bat
echo Y>"%TEMP%\%~nx0.run"					//临时目录下生成.run文件,内容为Y
if not exist "%TEMP%\%~nx0.run" goto mainEntry  //文件不存在,执行mainEntry
echo Y>"%TEMP%\%~nx0.Y"						//临时目录下生成.Y文件,内容为Y

//调用catalina.bat,%*所有参数空格分割的拼接串,如:e:\tomcat8\bin\catalina.bat arg1 arg2 Y
call "%~f0" %* <"%TEMP%\%~nx0.Y"			

set RETVAL=%ERRORLEVEL%				//脚本调用返回码
del /Q "%TEMP%\%~nx0.Y" >NUL 2>&1	//删除文件,/Q 静默删除,2>&1 成功和错误信息都输出到 NUL
exit /B %RETVAL%

:mainEntry
//安静删除temp目录下的catalina.bat.run文件,成功和错误信息都输出到nul
del /Q "%TEMP%\%~nx0.run" >NUL 2>&1	
set "CURRENT_DIR=%cd%"	// 设置CURRENT_DIR=当前目录
//CATALINA_HOME为空,跳到gotHome
if not "%CATALINA_HOME%" == "" goto gotHome
set "CATALINA_HOME=%CURRENT_DIR%"	//设置CATALINA_HOME=CURRENT_DIR
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome	//存在catalina.bat,执行okHome
cd ..	//跳到上层目录
set "CATALINA_HOME=%cd%"	//CATALINA_HOME当前目录
cd "%CURRENT_DIR%"			//进入CURRENT_DIR

:gotHome
// 存在catalina.bat,执行okHome
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome
echo The CATALINA_HOME environment variable is not defined correctly
echo This environment variable is needed to run this program
goto end

:okHome
rem Copy CATALINA_BASE from CATALINA_HOME if not defined
if not "%CATALINA_BASE%" == "" goto gotBase	//CATALINA_BASE不为空,执行gotBase
set "CATALINA_BASE=%CATALINA_HOME%"			//变量赋值

//bat逐行执行,okHome执行完毕后执行gotBase
:gotBase
// CATALINA_HOME=E:\tomcat8 没有分号 执行 homeNoSemicolon
if "%CATALINA_HOME%" == "%CATALINA_HOME:;=%" goto homeNoSemicolon
echo Using CATALINA_HOME:   "%CATALINA_HOME%"
echo Unable to start as CATALINA_HOME contains a semicolon (;) character
goto end

:homeNoSemicolon
// CATALINA_BASE=E:\tomcat8 没有分号 执行 baseNoSemicolon
if "%CATALINA_BASE%" == "%CATALINA_BASE:;=%" goto baseNoSemicolon
echo Using CATALINA_BASE:   "%CATALINA_BASE%"
echo Unable to start as CATALINA_BASE contains a semicolon (;) character
goto end

:baseNoSemicolon
rem Ensure that any user defined CLASSPATH variables are not used on startup,
rem but allow them to be specified in setenv.bat, in rare case when it is needed.
set CLASSPATH=
// 没有setenv.bat文件,执行checkSetenvHome
if not exist "%CATALINA_BASE%\bin\setenv.bat" goto checkSetenvHome
call "%CATALINA_BASE%\bin\setenv.bat"
goto setenvDone

:checkSetenvHome
if exist "%CATALINA_HOME%\bin\setenv.bat" call "%CATALINA_HOME%\bin\setenv.bat"

// 顺序执行,checkSetenvHome执行完执行setenvDone
:setenvDone
// 存在setclasspath.bat脚本,执行okSetclasspath
if exist "%CATALINA_HOME%\bin\setclasspath.bat" goto okSetclasspath
echo Cannot find "%CATALINA_HOME%\bin\setclasspath.bat"
echo This file is needed to run this program
goto end

:okSetclasspath
// 调用setclasspath.bat脚本,e:tomcat8\bin\setclasspath.bat start
// setclasspath.bat, 主要设置java_home,jre_home,java.exe路径
call "%CATALINA_HOME%\bin\setclasspath.bat" %1
if errorlevel 1 goto end	//errorlevel非0表示出错,结束脚本

//CLASSPATH为空,跳到emptyClasspath
if "%CLASSPATH%" == "" goto emptyClasspath
set "CLASSPATH=%CLASSPATH%;"

:emptyClasspath
//设置classpath,临时目录
set "CLASSPATH=%CLASSPATH%%CATALINA_HOME%\bin\bootstrap.jar"
if not "%CATALINA_TMPDIR%" == "" goto gotTmpdir
set "CATALINA_TMPDIR=%CATALINA_BASE%\temp"

// 顺序执行,emptyClasspath执行完执行gotTmpdir
// gotTmpdir执行到最后,跳到juliClasspathDone
:gotTmpdir
rem Add tomcat-juli.jar to classpath
rem tomcat-juli.jar can be over-ridden per instance
if not exist "%CATALINA_BASE%\bin\tomcat-juli.jar" goto juliClasspathHome
//设置变量为日志jar,tomcat-juli.jar路径
set "CLASSPATH=%CLASSPATH%;%CATALINA_BASE%\bin\tomcat-juli.jar"
goto juliClasspathDone

:juliClasspathHome
set "CLASSPATH=%CLASSPATH%;%CATALINA_HOME%\bin\tomcat-juli.jar"

//由gotTmpdir跳过来
:juliClasspathDone
if not "%JSSE_OPTS%" == "" goto gotJsseOpts
set JSSE_OPTS="-Djdk.tls.ephemeralDHKeySize=2048"	//本例因为JSSE_OPTS为空,会在此处赋值

// 顺序执行,juliClasspathDone后执行gotJsseOpts
:gotJsseOpts
set "JAVA_OPTS=%JAVA_OPTS% %JSSE_OPTS%"
if not "%LOGGING_CONFIG%" == "" goto noJuliConfig
set LOGGING_CONFIG=-Dnop
if not exist "%CATALINA_BASE%\conf\logging.properties" goto noJuliConfig
set LOGGING_CONFIG=-Djava.util.logging.config.file="%CATALINA_BASE%\conf\logging.properties"

// 顺序执行,gotJsseOpts后执行noJuliConfig
:noJuliConfig
set "JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG%"
if not "%LOGGING_MANAGER%" == "" goto noJuliManager
set LOGGING_MANAGER=-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager

// 顺序执行,noJuliConfig后执行noJuliManager,%1=start
:noJuliManager
set "JAVA_OPTS=%JAVA_OPTS% %LOGGING_MANAGER%"
echo Using CATALINA_BASE:   "%CATALINA_BASE%"
echo Using CATALINA_HOME:   "%CATALINA_HOME%"
echo Using CATALINA_TMPDIR: "%CATALINA_TMPDIR%"
if ""%1"" == ""debug"" goto use_jdk
echo Using JRE_HOME:        "%JRE_HOME%"
goto java_dir_displayed	//本例会执行java_dir_displayed

:use_jdk
echo Using JAVA_HOME:       "%JAVA_HOME%"

// 由noJuliManager跳过来
:java_dir_displayed
echo Using CLASSPATH:       "%CLASSPATH%"
set _EXECJAVA=%_RUNJAVA%
set MAINCLASS=org.apache.catalina.startup.Bootstrap
set ACTION=start
set SECURITY_POLICY_FILE=
set DEBUG_OPTS=
set JPDA=

if not ""%1"" == ""jpda"" goto noJpda	//%1=start, 所以会执行noJpda
set JPDA=jpda
if not "%JPDA_TRANSPORT%" == "" goto gotJpdaTransport
set JPDA_TRANSPORT=dt_socket
:gotJpdaTransport
if not "%JPDA_ADDRESS%" == "" goto gotJpdaAddress
set JPDA_ADDRESS=localhost:8000
:gotJpdaAddress
if not "%JPDA_SUSPEND%" == "" goto gotJpdaSuspend
set JPDA_SUSPEND=n
:gotJpdaSuspend
if not "%JPDA_OPTS%" == "" goto gotJpdaOpts
set JPDA_OPTS=-agentlib:jdwp=transport=%JPDA_TRANSPORT%,address=%JPDA_ADDRESS%,server=y,suspend=%JPDA_SUSPEND%
:gotJpdaOpts
shift

// 由java_dir_displayed跳过来,%1=start,因此会跳到doStart
:noJpda
if ""%1"" == ""debug"" goto doDebug
if ""%1"" == ""run"" goto doRun
if ""%1"" == ""start"" goto doStart
if ""%1"" == ""stop"" goto doStop
if ""%1"" == ""configtest"" goto doConfigTest
if ""%1"" == ""version"" goto doVersion

echo Usage:  catalina ( commands ... )
echo commands:
echo   debug             Start Catalina in a debugger
echo   debug -security   Debug Catalina with a security manager
echo   jpda start        Start Catalina under JPDA debugger
echo   run               Start Catalina in the current window
echo   run -security     Start in the current window with security manager
echo   start             Start Catalina in a separate window
echo   start -security   Start in a separate window with security manager
echo   stop              Stop Catalina
echo   configtest        Run a basic syntax check on server.xml
echo   version           What version of tomcat are you running?
goto end

:doDebug
shift
set _EXECJAVA=%_RUNJDB%
set DEBUG_OPTS=-sourcepath "%CATALINA_HOME%\..\..\java"
if not ""%1"" == ""-security"" goto execCmd
shift
echo Using Security Manager
set "SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy"
goto execCmd

:doRun
shift
if not ""%1"" == ""-security"" goto execCmd
shift
echo Using Security Manager
set "SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy"
goto execCmd

// 由noJpda跳过来
:doStart
shift		// %2 变成 %1
if "%TITLE%" == "" set TITLE=Tomcat		// 设置cmd命令框标题为Tomcat
set _EXECJAVA=start "%TITLE%" %_RUNJAVA%
if not ""%1"" == ""-security"" goto execCmd
shift
echo Using Security Manager
set "SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy"
goto execCmd

:doStop
shift
set ACTION=stop
set CATALINA_OPTS=
goto execCmd

:doConfigTest
shift
set ACTION=configtest
set CATALINA_OPTS=
goto execCmd

:doVersion
%_EXECJAVA% -classpath "%CATALINA_HOME%\lib\catalina.jar" org.apache.catalina.util.ServerInfo
goto end

// 由doStart跳过来
:execCmd
rem Get remaining unshifted command line arguments and save them in the
set CMD_LINE_ARGS=

// execCmd 顺序执行而来
:setArgs
// startup.bat start 带入的参数在之前的shift 操作中已经移出,此处%1为空,跳到doneSetArgs
if ""%1""=="""" goto doneSetArgs
set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
shift
goto setArgs

//由setArgs跳过来
:doneSetArgs
rem Execute Java with the applicable properties
if not "%JPDA%" == "" goto doJpda
if not "%SECURITY_POLICY_FILE%" == "" goto doSecurity
//执行 %_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION% 随后脚本结束
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto end

:doSecurity
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Djava.security.manager -Djava.security.policy=="%SECURITY_POLICY_FILE%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto end
:doJpda
if not "%SECURITY_POLICY_FILE%" == "" goto doSecurityJpda
%_EXECJAVA% %JAVA_OPTS% %JPDA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto end
:doSecurityJpda
%_EXECJAVA% %JAVA_OPTS% %JPDA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Djava.security.manager -Djava.security.policy=="%SECURITY_POLICY_FILE%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto end

:end
3、代码说明

因为catalina.bat脚本确实有点长,里面的跳转比较多,看起来不够直接,这儿列出catalina.bat脚本的跳转关系,以startup.bat 调用catalina.bat start为例。

if not ""%1"" == ""run"" goto mainEntry

:mainEntry
if not "%CATALINA_HOME%" == "" goto gotHome

:gotHome
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome

:okHome
set "CATALINA_BASE=%CATALINA_HOME%"
顺序执行gotBase

:gotBase
if "%CATALINA_HOME%" == "%CATALINA_HOME:;=%" goto homeNoSemicolon

:homeNoSemicolon
if "%CATALINA_BASE%" == "%CATALINA_BASE:;=%" goto baseNoSemicolon

:baseNoSemicolon
if not exist "%CATALINA_BASE%\bin\setenv.bat" goto checkSetenvHome
顺序执行setenvDone

:setenvDone
if exist "%CATALINA_HOME%\bin\setclasspath.bat" goto okSetclasspath

:okSetclasspath
if "%CLASSPATH%" == "" goto emptyClasspath

:emptyClasspath
按顺序执行 gotTmpdir

:gotTmpdir
//E:\tomcat8\bin\tomcat-juli.jar
set "CLASSPATH=%CLASSPATH%;%CATALINA_BASE%\bin\tomcat-juli.jar"
goto juliClasspathDone

:juliClasspathDone
set JSSE_OPTS="-Djdk.tls.ephemeralDHKeySize=2048"

:gotJsseOpts
会顺序执行到 :noJuliConfig

:noJuliConfig
会顺序执行到 :noJuliManager

:noJuliManager
会顺序执行到goto java_dir_displayed

:java_dir_displayed
if not ""%1"" == ""jpda"" goto noJpda, 会跳到noJpda

:noJpda
if ""%1"" == ""start"" goto doStart, 会跳到doStart

:doStart
if not ""%1"" == ""-security"" goto execCmd, 会跳到execCmd

:execCmd
set CMD_LINE_ARGS=

:setArgs
if ""%1""=="""" goto doneSetArgs

:doneSetArgs
//start "Tomcat" "E:\software\java\jdk1.8.0_92\bin\java.exe"  "-Djdk.tls.ephemeralDHKeySize=2048" -Djava.util.logging.config.file="E:\tomcat8\conf\logging.properties" -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager   -Djava.endorsed.dirs="E:\tomcat8\endorsed" -classpath "E:\tomcat8\bin\bootstrap.jar;E:\tomcat8\bin\tomcat-juli.jar" -Dcatalina.base="E:\tomcat8" -Dcatalina.home="E:\tomcat8" -Djava.io.tmpdir="E:\tomcat8\temp" org.apache.catalina.startup.Bootstrap  start
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto end

脚本最后调用的是:

start "Tomcat" "E:\software\java\jdk1.8.0_92\bin\java.exe"  "-Djdk.tls.ephemeralDHKeySize=2048" -Djava.util.logging.config.file="E:\tomcat8\conf\logging.properties" -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager   -Djava.endorsed.dirs="E:\tomcat8\endorsed" -classpath "E:\tomcat8\bin\bootstrap.jar;E:\tomcat8\bin\tomcat-juli.jar" -Dcatalina.base="E:\tomcat8" -Dcatalina.home="E:\tomcat8" -Djava.io.tmpdir="E:\tomcat8\temp" org.apache.catalina.startup.Bootstrap  start

启动java进程,运行org.apache.catalina.startup.Bootstrap类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值