tomcat启动批处理——catalina.bat


这个批处理才是tomcat服务器启动跟关闭的核心脚本。当中包括。。。。(各种变量),此节将具体解说这个批处理的逻辑。


先看看第一部分脚本:
********************************************************************************************
if not ""%1"" == ""run"" goto mainEntry
if "%TEMP%" == "" goto mainEntry
if exist "%TEMP%\%~nx0.run" goto mainEntry
echo Y>"%TEMP%\%~nx0.run"
if not exist "%TEMP%\%~nx0.run" goto mainEntry
echo Y>"%TEMP%\%~nx0.Y"
call "%~f0" %* <"%TEMP%\%~nx0.Y"
set RETVAL=%ERRORLEVEL%
del /Q "%TEMP%\%~nx0.Y" >NUL 2>&1
exit /B %RETVAL%
:mainEntry
del /Q "%TEMP%\%~nx0.run" >NUL 2>&1
********************************************************************************************
第一行推断假设%1即第一个參数等于run则直接跳到mainEntry,使用两个双引號是为了防止參数中带有空格;第二行推断TEMP环境变量为空的话则直接跳到mainEntry;第三行推断假设TEMP环境变量文件夹下存在catalina.bat.run文件则直接跳到mainEntry;第四行把字母Y输入catalina.bat.run文件里;第五行推断假设不存在catalina.bat.run文件则跳到mainEntry;第六行将字母Y输入到catalina.bat.Y文件里;第七行以catalina.bat.Y作为输入运行当前批处理。%*表示全部的參数;第八行把上面运行后的%ERRORLEVEL%变量赋值给RETVAL,假设运行过程出现故障则为非零值;第九行删除catalina.bat.Y文件,而且不输出运行结果。另外把标准错误输出STDERR重定向到标准输出STDOUT。第十行退出当前批处理脚本,并把RETVAL变量作为返回值。剩下两行脚本不再赘述。


第二部分脚本主要是设置CATALINA_HOME、CATALINA_BASE两个变量。
********************************************************************************************
set "CURRENT_DIR=%cd%"
if not "%CATALINA_HOME%" == "" goto gotHome
set "CATALINA_HOME=%CURRENT_DIR%"
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome
cd ..
set "CATALINA_HOME=%cd%"
cd "%CURRENT_DIR%"
:gotHome
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome
goto end
:okHome
if not "%CATALINA_BASE%" == "" goto gotBase
set "CATALINA_BASE=%CATALINA_HOME%"
:gotBase
********************************************************************************************
设置CATALINA_HOME环境变量,逻辑跟startup.bat的一样,这里为什么还要进行一次CATALINA_HOME设置环境变量呢?简单地说。是为了支持用户直接运行catalina.bat,而非通过startup.bat运行。接着设置CATALINA_BASE环境变量。这里直接把CATALINA_HOME的值赋给它了。


第三部分脚本主要是设置CLASSPATH环境变量。把各种须要的jar包加入到CLASSPATH下。


********************************************************************************************
set CLASSPATH= 
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"
:setenvDone
if exist "%CATALINA_HOME%\bin\setclasspath.bat" goto okSetclasspath
goto end
:okSetclasspath
call "%CATALINA_HOME%\bin\setclasspath.bat" %1
if errorlevel 1 goto end
if "%CLASSPATH%" == "" goto emptyClasspath
set "CLASSPATH=%CLASSPATH%;"
:emptyClasspath
set "CLASSPATH=%CLASSPATH%%CATALINA_HOME%\bin\bootstrap.jar"
if not "%CATALINA_TMPDIR%" == "" goto gotTmpdir
set "CATALINA_TMPDIR=%CATALINA_BASE%\temp"
:gotTmpdir
if not exist "%CATALINA_BASE%\bin\tomcat-juli.jar" goto juliClasspathHome
set "CLASSPATH=%CLASSPATH%;%CATALINA_BASE%\bin\tomcat-juli.jar"
goto juliClasspathDone
:juliClasspathHome
set "CLASSPATH=%CLASSPATH%;%CATALINA_HOME%\bin\tomcat-juli.jar"
:juliClasspathDone
********************************************************************************************
把CLASSPATH设为空,推断%CATALINA_BASE%\bin文件夹下是否存在setenv.bat。假设存在则调用此批处理文件,否则推断%CATALINA_HOME%\bin文件夹下是否存在setenv.bat,如存在则运行;往下继续推断是否存在%CATALINA_HOME%\bin\setclasspath.bat文件,这里假设不存在则直接跳到结尾,表明这个setclasspath.bat是必要的批处理脚本,接着运行setclasspath.bat脚本,%1表示參数。if errorlevel 1 goto end表示运行到此假设错误值大于等于1则直接跳到结尾。假设没有错误,则继续往下,推断环境变量%CLASSPATH%是否为空。不为空则把CLASSPATH设置为%CLASSPATH%并加上分号。此后把%CATALINA_HOME%\bin\bootstrap.jar加入到classpath中,这个包是tomcat的内核。紧接着设置暂时文件夹temp,追加tomcat-juli.jar包到classpath中,基本逻辑是先从%CATALINA_BASE%\bin文件夹下找,不存在的话再去%CATALINA_HOME%\bin文件夹下找。tomcat-juli.jar这个包主要包括tomcat系统日志处理类,详情请重温第三部分的第四节——日志框架。
第四部分是对日志配置的设置。


********************************************************************************************
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"
: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
:noJuliManager
set JAVA_OPTS=%JAVA_OPTS% %LOGGING_MANAGER%
********************************************************************************************
Tomcat中的日志实现是用jdk自带的日志工具类,当中主要有两项属性能够配置,分别为java.util.logging.config.file跟java.util.logging.manager。首先推断环境变量是否存在LOGGING_CONFIG。存在即直接使用。否则把LOGGING_CONFIG设为-Dnop,而且往下推断是否存在%CATALINA_BASE%\conf\logging.properties,如存在则又把LOGGING_CONFIG设为-Djava.util.logging.config.file="%CATALINA_BASE%\conf\logging.properties"。

特别说明一下set JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG%,你会发现原版的脚步前面即没有JAVA_OPTS这个变量。也没有JAVA_OPTS这个环境变量,这样做的目的是为了把全部參数都能追加到JAVA_OPTS上。比方运维人员在前面已经有了JAVA_OPTS这个变量,运行到此便会追加到JAVA_OPTS后面,假如前面没有JAVA_OPTS变量则作为空值。不影响运行。对于LOGGING_MANAGER变量的设置跟LOGGING_CONFIG同一个道理。


第五部分是运行命令前一些參数的初始化。


********************************************************************************************
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
set JPDA=jpda
if not "%JPDA_TRANSPORT%" == "" goto gotJpdaTransport
set JPDA_TRANSPORT=dt_socket
:gotJpdaTransport
if not "%JPDA_ADDRESS%" == "" goto gotJpdaAddress
set JPDA_ADDRESS=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
:noJpda
********************************************************************************************
把%_RUNJAVA%变量赋给_EXECJAVA,%_RUNJAVA%变量在setclasspath.bat 脚本中已经被设置为%JRE_HOME%\bin\java。设置MAINCLASS为tomcat的启动类Bootstrap,ACTION为start。其它变量先不初始化。

假设第一个參数为jpda,则把JPDA变量设为值jpda,jpda即是Java 平台调试体系结构,它能够提供非常方便的远程调试;假设JPDA_TRANSPORT变量为空则设为dt_socket。假设JPDA_ADDRESS变量为空则设置为8000;假设JPDA_SUSPEND变量为空则设为n;假设JPDA_OPTS变量为空则设为-agentlib:jdwp=transport=%JPDA_TRANSPORT%,address=%JPDA_ADDRESS%,server=y,suspend=%JPDA_SUSPEND%。

最后用了一个shift,把參数前移一位。

这段主要初始化JPDA启动命令项,把JDWP代理载入到应用程序的JVM。
第六部分命令主要是依据不同的參数跳转到不同的位置运行不同命令,事实上也是组装一些參数。为下一步真正运行命令做准备。
********************************************************************************************
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
:doDebug
shift
set _EXECJAVA=%_RUNJDB%
set DEBUG_OPTS=-sourcepath "%CATALINA_HOME%\..\..\java"
if not ""%1"" == ""-security"" goto execCmd
shift
set "SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy"
goto execCmd
:doRun
shift
if not ""%1"" == ""-security"" goto execCmd
shift
set "SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy"
goto execCmd
:doStart
shift
if not "%OS%" == "Windows_NT" goto noTitle
if "%TITLE%" == "" set TITLE=Tomcat
set _EXECJAVA=start "%TITLE%" %_RUNJAVA%
goto gotTitle
:noTitle
set _EXECJAVA=start %_RUNJAVA%
:gotTitle
if not ""%1"" == ""-security"" goto execCmd
shift
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
********************************************************************************************
前面已经用shift把參数前移一位,此时%1表示的參数已经是下一个參数,分别依照debug、run、start、stop、configtest、version跳到doDebug、doRun、doStart、doStop、doConfigTest、doVersion标签位置运行不同的操作。

以下对这六个操作进行分析:
doDebug的逻辑是。把參数前移一位。设置_EXECJAVA变量赋为%_RUNJDB%,_RUNJDB变量在setclasspath批处理脚本已经被设置为%JAVA_HOME%\bin\jdb,设置DEBUG_OPTS变量,接着推断參数是否等于-security,即是否启动安全管理器,假设没有则直接跳到execCmd位置,否则把參数前移一位,而且设置SECURITY_POLICY_FILE变量为%CATALINA_BASE%\conf\catalina.policy,这个catalina.policy有什么作用请參考第三部分第四节安全框架内容。最后跳到execCmd位置。
doRun的逻辑是。把參数前移一位,推断是否使用安全管理器,假设不使用安全管理器则直接跳到execCmd位置,否则參数前移一位,再设置SECURITY_POLICY_FILE变量。最后跳到execCmd位置。
doStart的逻辑是,把參数前移一位,依据系统是不是Windows_NT系统设置命令窗体的标题。TITLE变量被设置为Tomcat字符串。

设置_EXECJAVA变量,假设有标题则加入到启动命令中,接着推断是否使用安全管理器。把參数前移一位并设置SECURITY_POLICY_FILE,最后跳到execCmd位置。
doStop、doConfigTest的逻辑几乎相同,把參数前移一位,设置ACTION变量为stop、configtest,清空CATALINA_OPTS变量,跳到execCmd位置。


doVersion事实上就是显示服务器的信息,直接调用%JRE_HOME%\bin文件夹下的 java.exe程序,%CATALINA_HOME%\lib\catalina.jar作为classpath, org.apache.catalina.util.ServerInfo作为启动类,就可以输出服务器相关信息。然后结束命令。
    第七部分命令的运行。
********************************************************************************************
:execCmd
set CMD_LINE_ARGS=
:setArgs
if ""%1""=="""" goto doneSetArgs
set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
shift
goto setArgs
:doneSetArgs
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%
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% %CATALINA_OPTS% %JPDA_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% %CATALINA_OPTS% %JPDA_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-2-1-2,主要是用JPDA、SECURITY_POLICY_FILE两个变量进行推断,分别代表是否使用Java平台调试体系结构跟安全管理器。这种话就能组成四种不同的命令,往下看看最全面的命令的具体信息:
 
图3-2-1-2
    假设既使用安全管理器又使用Java平台调试体系来启动,则会跳到doSecurityJpda位置。此时
%_EXECJAVA%为:start "Tomcat" "D:\java\jdk\bin\java"(假设java安装路径为D:\java\jdk)。
%JAVA_OPTS%为:-Djava.util.logging.config.file="D:\java\apache-tomcat-7.0.39\conf\logging.properties" -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager。


%CATALINA_OPTS%为:空。
%JPDA_OPTS%为:-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n。
%DEBUG_OPTS%为:空。
%JAVA_ENDORSED_DIRS%为:"D:\apache-tomcat\endorsed"(假设tomcat安装文件夹为D:\apache-tomcat)。


%CLASSPATH%为:"D:\apache-tomcat\bin\bootstrap.jar;D:\apache-tomcat\bin\tomcat-juli.jar"。


%SECURITY_POLICY_FILE%为:D:\apache-tomcat\conf\catalina.policy。
%CATALINA_BASE%为:D:\apache-tomcat。


%CATALINA_HOME%为:D:\apache-tomcat。
%CATALINA_TMPDIR%为:D:\apache-tomcat\temp。
%MAINCLASS%为:org.apache.catalina.startup.Bootstrap。


%CMD_LINE_ARGS%为:空。


%ACTION%为:start。

将以上的变量值组装成一个命令行就是终于启动的脚本了。


点击订购作者《Tomcat内核设计剖析》




posted on 2017-05-29 14:59  wgwyanfs  阅读(578)  评论(0编辑  收藏  举报

导航