2025年5月21日 星期三 乙巳(蛇)年 二月廿三 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > DOS/BAT与(脚本)

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

时间:04-14来源:作者:点击数:54

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 //errorlevel0表示出错,结束脚本
  • //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类。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门