赞
踩
Windows下,Tomcat可以以服务形式启动、停止,也可以执行脚本启动(startup.bat)、停止(shutdown.bat)。执行startup.bat时会调用catalina.bat,catalina.bat脚本又会调用setclasspath.bat进行java class path指定。上篇讲了startup.bat启动代码实现,本文将剖析catalina.bat的代码实现。
版本:8.0.36
安装目录:E:\tomcat8
由于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
因为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类。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。