• 运行startup.bat的启动过程


    一、前言

    一般启动tomcat都是找到bin目录下的startup.bat(windows)下或者startup.sh(linux下),所以要研究tomcat的启动,startup脚本是避不开的。那么下面就来看一看windows下面的startup.bat。

    二、bat文件

    要看懂startup.bat,首先得对bat文件有个基本的了解。

    bat文件是dos下的批处理文件。批处理文件是无格式的文本文件,这个文件的每一行都是一条DOS命令。它的文件扩展名为 .bat 或 .cmd。在命令提示下键入批处理文件的名称,或者双击该批处理文件,系统就会调用cmd.exe按照该文件中各个命令出现的顺序来逐个运行它们。使用批处理文件(也被称为批处理程序或脚本),可以简化日常或重复性任务。

    批处理简单语法:

    rem: 该命令用于注释,rem起始的行不会作为代码执行
    pause: 该命令用于暂停正在执行的批处理文件,并且提示用户按键,然后程序继续执行
    echo: 该命令用于在dos控制台显示一段文本,相当于print,如果想要显示环境变量需要在环境变量前后加上%,例如显示操作系统 echo %OS%
    echo off: 该命令可以防止将批处理文件中的具体命令打印出来,而只会输出执行结果。
    @echo off:该命令与echo off相同,唯一的区别在于 @echo off不仅会隐藏具体命令还会连'echo off'这个自身命令也隐藏起来。
    set: 设置环境变量,例如 set A = 100 设置A变量为100
    label: 使用 ':'(冒号)来设置一个标签,供给goto命令使用,例如":init"代表一个init标签。
    goto: 该命令使正在执行的命令强制跳转到他指定的标签。例如我需要跳转指定A标签下的命令,如下:goto A
    not: 该命令用来取反,相当于逻辑非。
    if: 该命令表示判断
    exist: 该命令通常用来测试文件是否存在,一般和if一起使用
    shift: 该命令用来将参数后移一位即将%2%赋值给%1%,%3%赋值给%2%,也可以理解为参数列表左移即删除现有参数列表的第一位。
    call: 该命令用来调用另外一条命令。
    setLocal: 该命令表示该批处理文件中修改的环境变量只在本文件中起作用,或者直到endLocal命令出现,被修改的环境变量才恢复原状。
    start: 重新开启一个dos窗口。

    可以参考一下这篇博文:

    Bat命令学习

    三、startup.bat

    用编辑器打开startup.bat文件,内容如下:

     1 @echo off
     2 rem Licensed to the Apache Software Foundation (ASF) under one or more
     3 rem contributor license agreements.  See the NOTICE file distributed with
     4 rem this work for additional information regarding copyright ownership.
     5 rem The ASF licenses this file to You under the Apache License, Version 2.0
     6 rem (the "License"); you may not use this file except in compliance with
     7 rem the License.  You may obtain a copy of the License at
     8 rem
     9 rem     http://www.apache.org/licenses/LICENSE-2.0
    10 rem
    11 rem Unless required by applicable law or agreed to in writing, software
    12 rem distributed under the License is distributed on an "AS IS" BASIS,
    13 rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14 rem See the License for the specific language governing permissions and
    15 rem limitations under the License.
    16 
    17 rem ---------------------------------------------------------------------------
    18 rem Start script for the CATALINA Server
    19 rem ---------------------------------------------------------------------------
    20 
    21 setlocal
    22 
    23 rem Guess CATALINA_HOME if not defined
    24 set "CURRENT_DIR=%cd%"
    25 if not "%CATALINA_HOME%" == "" goto gotHome
    26 set "CATALINA_HOME=%CURRENT_DIR%"
    27 if exist "%CATALINA_HOME%incatalina.bat" goto okHome
    28 cd ..
    29 set "CATALINA_HOME=%cd%"
    30 cd "%CURRENT_DIR%"
    31 :gotHome
    32 if exist "%CATALINA_HOME%incatalina.bat" goto okHome
    33 echo The CATALINA_HOME environment variable is not defined correctly
    34 echo This environment variable is needed to run this program
    35 goto end
    36 :okHome
    37 
    38 set "EXECUTABLE=%CATALINA_HOME%incatalina.bat"
    39 
    40 rem Check that target executable exists
    41 if exist "%EXECUTABLE%" goto okExec
    42 echo Cannot find "%EXECUTABLE%"
    43 echo This file is needed to run this program
    44 goto end
    45 :okExec
    46 
    47 rem Get remaining unshifted command line arguments and save them in the
    48 set CMD_LINE_ARGS=
    49 :setArgs
    50 if ""%1""=="""" goto doneSetArgs
    51 set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
    52 shift
    53 goto setArgs
    54 :doneSetArgs
    55 
    56 call "%EXECUTABLE%" start %CMD_LINE_ARGS%
    57 
    58 :end

    @echo off,此语句常用于开头,表示不显示所有的命令行信息,包括此句。

    然后是一大段rem后面的内容,是注释,对软件的License做了说明,英文不太好,就不翻译了。

    setlocal,启动批处理文件中环境变量的本地化,本地化将持续到出现匹配的endlocal命令或者到达批处理文件结尾为止。

    下面将批处理文件拆成几段看:

    第一段:判断CATALINA_HOME是否定义

     1 setlocal
     2 
     3 rem Guess CATALINA_HOME if not defined
     4 set "CURRENT_DIR=%cd%"
     5 if not "%CATALINA_HOME%" == "" goto gotHome
     6 set "CATALINA_HOME=%CURRENT_DIR%"
     7 if exist "%CATALINA_HOME%incatalina.bat" goto okHome
     8 cd ..
     9 set "CATALINA_HOME=%cd%"
    10 cd "%CURRENT_DIR%"
    1. 设置变量CURRENT_DIR为当前目录,一般打开的就是tomcat的bin目录,./apache-tomcat-x.x.xx/bin;

    2. 判断系统变量CATALINA_HOME是不是空串(一般安装tomcat时,我们都会配置CATALINA_HOME环境变量,不知有没有印象呢),如果是就跳转到gotHome标签执行,假设CATALINA_HOME环境变量没有定义,就继续往下;

    3. 设置CATALINA_HOME为CURRENT_DIR指向的目录,也就是bin目录(./apache-tomcat-x.x.xx/bin);

    4. 判断CATALINA_HOMEincatalina.bat文件是否存在,也就是 ./apache-tomcat-x.x.xx/bin/bin/catalina.bat,如果存在就转向okHome标签,显然是不存在的,所以不会跳转到okHome,继续往下;

    5. 不存在的话,CATALINA_HOME取上级目录的值,也就是(./apache-tomcat-x.x.xx/);

    6. 设置CATALINA_HOME指向当前目录,也就是Tomcat的根目录;

    7. 进入 CURRENT_DIR(./apache-tomcat-x.x.xx/bin);

    第二段:执行gotHome标签

    1 :gotHome
    2 if exist "%CATALINA_HOME%incatalina.bat" goto okHome
    3 echo The CATALINA_HOME environment variable is not defined correctly
    4 echo This environment variable is needed to run this program
    5 goto end

    通过上面的设置,CATALINA_HOME的值已经是: ./apache-tomcat-x.x.xx/,这时判断./apache-tomcat-x.x.xx/catalina.bat 脚本是否存在,如果不存在,则输出一些信息结束,一般这时是可以找到的,所以跳转到okHome标签处;

    第三段:执行okHome标签

    1 :okHome
    2 
    3 set "EXECUTABLE=%CATALINA_HOME%incatalina.bat"

    设置EXECUTABLE变量指向为catalina.bat脚本;

    第四段:再次检查catalina.bat是否存在

    1 rem Check that target executable exists 2 if exist "%EXECUTABLE%" goto okExec 3 echo Cannot find "%EXECUTABLE%" 4 echo This file is needed to run this program 5 goto end

    双重保险继续判断下EXECUTABLE指向的catalina.bat文件是否存在,不存在就输出提示信息并且结束,存在就跳转到okExec标签处:

    第五段:

     1 :okExec
     2 
     3 rem Get remaining unshifted command line arguments and save them in the
     4 set CMD_LINE_ARGS=
     5 :setArgs
     6 if ""%1""=="""" goto doneSetArgs
     7 set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
     8 shift
     9 goto setArgs
    10 :doneSetArgs
    11 
    12 call "%EXECUTABLE%" start %CMD_LINE_ARGS%
    1. set CMD_LINE_ARGS=表示清空变量CMD_LINE_ARGS;
    2. 执行setArgs标签;
    3. 第一个变量(%1%)为空字符串,那么就跳转到doneSetArgs标签,一般情况下,直接运行startup.bat,是没有传递任何参数,所以是跳转到doneSetArgs标签,由此也可以猜想出,如果不是使用双击执行的话,使用命令行启动startup.bat那么是可以传递参数的;
    4. 跳转到doneSetArgs,调用EXECUTABLE指向的文件,也就是catalina.bat文件,同时传递start参数,因为CMD_LINE_ARGS为空,所以只传递了一个start参数

    **最后:**end标签

    1 :end

    判断失败跳转的标签,是参数不正确的时候的结束标志。

    四、catalina.bat

    如果startup.bat执行正确,就等同于运行catalina.bat start,进入了catalina.bat脚本中,将脚本前面的一大段注释删掉了,如下:

      1 setlocal
      2 
      3 rem Suppress Terminate batch job on CTRL+C
      4 if not ""%1"" == ""run"" goto mainEntry
      5 if "%TEMP%" == "" goto mainEntry
      6 if exist "%TEMP%\%~nx0.run" goto mainEntry
      7 echo Y>"%TEMP%\%~nx0.run"
      8 if not exist "%TEMP%\%~nx0.run" goto mainEntry
      9 echo Y>"%TEMP%\%~nx0.Y"
     10 call "%~f0" %* <"%TEMP%\%~nx0.Y"
     11 rem Use provided errorlevel
     12 set RETVAL=%ERRORLEVEL%
     13 del /Q "%TEMP%\%~nx0.Y" >NUL 2>&1
     14 exit /B %RETVAL%
     15 :mainEntry
     16 del /Q "%TEMP%\%~nx0.run" >NUL 2>&1
     17 
     18 rem Guess CATALINA_HOME if not defined
     19 set "CURRENT_DIR=%cd%"
     20 if not "%CATALINA_HOME%" == "" goto gotHome
     21 set "CATALINA_HOME=%CURRENT_DIR%"
     22 if exist "%CATALINA_HOME%incatalina.bat" goto okHome
     23 cd ..
     24 set "CATALINA_HOME=%cd%"
     25 cd "%CURRENT_DIR%"
     26 :gotHome
     27 
     28 if exist "%CATALINA_HOME%incatalina.bat" goto okHome
     29 echo The CATALINA_HOME environment variable is not defined correctly
     30 echo This environment variable is needed to run this program
     31 goto end
     32 :okHome
     33 
     34 rem Copy CATALINA_BASE from CATALINA_HOME if not defined
     35 if not "%CATALINA_BASE%" == "" goto gotBase
     36 set "CATALINA_BASE=%CATALINA_HOME%"
     37 :gotBase
     38 
     39 rem Ensure that neither CATALINA_HOME nor CATALINA_BASE contains a semi-colon
     40 rem as this is used as the separator in the classpath and Java provides no
     41 rem mechanism for escaping if the same character appears in the path. Check this
     42 rem by replacing all occurrences of ';' with '' and checking that neither
     43 rem CATALINA_HOME nor CATALINA_BASE have changed
     44 if "%CATALINA_HOME%" == "%CATALINA_HOME:;=%" goto homeNoSemicolon
     45 echo Using CATALINA_HOME:   "%CATALINA_HOME%"
     46 echo Unable to start as CATALINA_HOME contains a semicolon (;) character
     47 goto end
     48 :homeNoSemicolon
     49 
     50 if "%CATALINA_BASE%" == "%CATALINA_BASE:;=%" goto baseNoSemicolon
     51 echo Using CATALINA_BASE:   "%CATALINA_BASE%"
     52 echo Unable to start as CATALINA_BASE contains a semicolon (;) character
     53 goto end
     54 :baseNoSemicolon
     55 
     56 rem Ensure that any user defined CLASSPATH variables are not used on startup,
     57 rem but allow them to be specified in setenv.bat, in rare case when it is needed.
     58 set CLASSPATH=
     59 
     60 rem Get standard environment variables
     61 if not exist "%CATALINA_BASE%insetenv.bat" goto checkSetenvHome
     62 call "%CATALINA_BASE%insetenv.bat"
     63 goto setenvDone
     64 :checkSetenvHome
     65 if exist "%CATALINA_HOME%insetenv.bat" call "%CATALINA_HOME%insetenv.bat"
     66 :setenvDone
     67 
     68 rem Get standard Java environment variables
     69 if exist "%CATALINA_HOME%insetclasspath.bat" goto okSetclasspath
     70 echo Cannot find "%CATALINA_HOME%insetclasspath.bat"
     71 echo This file is needed to run this program
     72 goto end
     73 :okSetclasspath
     74 call "%CATALINA_HOME%insetclasspath.bat" %1
     75 if errorlevel 1 goto end
     76 
     77 rem Add on extra jar file to CLASSPATH
     78 rem Note that there are no quotes as we do not want to introduce random
     79 rem quotes into the CLASSPATH
     80 if "%CLASSPATH%" == "" goto emptyClasspath
     81 set "CLASSPATH=%CLASSPATH%;"
     82 :emptyClasspath
     83 set "CLASSPATH=%CLASSPATH%%CATALINA_HOME%inootstrap.jar"
     84 
     85 if not "%CATALINA_TMPDIR%" == "" goto gotTmpdir
     86 set "CATALINA_TMPDIR=%CATALINA_BASE%	emp"
     87 :gotTmpdir
     88 
     89 rem Add tomcat-juli.jar to classpath
     90 rem tomcat-juli.jar can be over-ridden per instance
     91 if not exist "%CATALINA_BASE%in	omcat-juli.jar" goto juliClasspathHome
     92 set "CLASSPATH=%CLASSPATH%;%CATALINA_BASE%in	omcat-juli.jar"
     93 goto juliClasspathDone
     94 :juliClasspathHome
     95 set "CLASSPATH=%CLASSPATH%;%CATALINA_HOME%in	omcat-juli.jar"
     96 :juliClasspathDone
     97 
     98 if not "%JSSE_OPTS%" == "" goto gotJsseOpts
     99 set JSSE_OPTS="-Djdk.tls.ephemeralDHKeySize=2048"
    100 :gotJsseOpts
    101 set "JAVA_OPTS=%JAVA_OPTS% %JSSE_OPTS%"
    102 
    103 rem Register custom URL handlers
    104 rem Do this here so custom URL handles (specifically 'war:...') can be used in the security policy
    105 set "JAVA_OPTS=%JAVA_OPTS% -Djava.protocol.handler.pkgs=org.apache.catalina.webresources"
    106 
    107 if not "%LOGGING_CONFIG%" == "" goto noJuliConfig
    108 set LOGGING_CONFIG=-Dnop
    109 if not exist "%CATALINA_BASE%conflogging.properties" goto noJuliConfig
    110 set LOGGING_CONFIG=-Djava.util.logging.config.file="%CATALINA_BASE%conflogging.properties"
    111 :noJuliConfig
    112 
    113 if not "%LOGGING_MANAGER%" == "" goto noJuliManager
    114 set LOGGING_MANAGER=-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
    115 :noJuliManager
    116 
    117 rem Configure JAVA 9 specific start-up parameters
    118 set "JDK_JAVA_OPTIONS=%JDK_JAVA_OPTIONS% --add-opens=java.base/java.lang=ALL-UNNAMED"
    119 set "JDK_JAVA_OPTIONS=%JDK_JAVA_OPTIONS% --add-opens=java.base/java.io=ALL-UNNAMED"
    120 set "JDK_JAVA_OPTIONS=%JDK_JAVA_OPTIONS% --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED"
    121 
    122 rem Java 9 no longer supports the java.endorsed.dirs
    123 rem system property. Only try to use it if
    124 rem JAVA_ENDORSED_DIRS was explicitly set
    125 rem or CATALINA_HOME/endorsed exists.
    126 set ENDORSED_PROP=ignore.endorsed.dirs
    127 if "%JAVA_ENDORSED_DIRS%" == "" goto noEndorsedVar
    128 set ENDORSED_PROP=java.endorsed.dirs
    129 goto doneEndorsed
    130 :noEndorsedVar
    131 if not exist "%CATALINA_HOME%endorsed" goto doneEndorsed
    132 set ENDORSED_PROP=java.endorsed.dirs
    133 :doneEndorsed
    134 
    135 rem ----- Execute The Requested Command ---------------------------------------
    136 
    137 echo Using CATALINA_BASE:   "%CATALINA_BASE%"
    138 echo Using CATALINA_HOME:   "%CATALINA_HOME%"
    139 echo Using CATALINA_TMPDIR: "%CATALINA_TMPDIR%"
    140 if ""%1"" == ""debug"" goto use_jdk
    141 echo Using JRE_HOME:        "%JRE_HOME%"
    142 goto java_dir_displayed
    143 :use_jdk
    144 echo Using JAVA_HOME:       "%JAVA_HOME%"
    145 :java_dir_displayed
    146 echo Using CLASSPATH:       "%CLASSPATH%"
    147 
    148 set _EXECJAVA=%_RUNJAVA%
    149 set MAINCLASS=org.apache.catalina.startup.Bootstrap
    150 set ACTION=start
    151 set SECURITY_POLICY_FILE=
    152 set DEBUG_OPTS=
    153 set JPDA=
    154 
    155 if not ""%1"" == ""jpda"" goto noJpda
    156 set JPDA=jpda
    157 if not "%JPDA_TRANSPORT%" == "" goto gotJpdaTransport
    158 set JPDA_TRANSPORT=dt_socket
    159 :gotJpdaTransport
    160 if not "%JPDA_ADDRESS%" == "" goto gotJpdaAddress
    161 set JPDA_ADDRESS=localhost:8000
    162 :gotJpdaAddress
    163 if not "%JPDA_SUSPEND%" == "" goto gotJpdaSuspend
    164 set JPDA_SUSPEND=n
    165 :gotJpdaSuspend
    166 if not "%JPDA_OPTS%" == "" goto gotJpdaOpts
    167 set JPDA_OPTS=-agentlib:jdwp=transport=%JPDA_TRANSPORT%,address=%JPDA_ADDRESS%,server=y,suspend=%JPDA_SUSPEND%
    168 :gotJpdaOpts
    169 shift
    170 :noJpda
    171 
    172 if ""%1"" == ""debug"" goto doDebug
    173 if ""%1"" == ""run"" goto doRun
    174 if ""%1"" == ""start"" goto doStart
    175 if ""%1"" == ""stop"" goto doStop
    176 if ""%1"" == ""configtest"" goto doConfigTest
    177 if ""%1"" == ""version"" goto doVersion
    178 
    179 echo Usage:  catalina ( commands ... )
    180 echo commands:
    181 echo   debug             Start Catalina in a debugger
    182 echo   debug -security   Debug Catalina with a security manager
    183 echo   jpda start        Start Catalina under JPDA debugger
    184 echo   run               Start Catalina in the current window
    185 echo   run -security     Start in the current window with security manager
    186 echo   start             Start Catalina in a separate window
    187 echo   start -security   Start in a separate window with security manager
    188 echo   stop              Stop Catalina
    189 echo   configtest        Run a basic syntax check on server.xml
    190 echo   version           What version of tomcat are you running?
    191 goto end
    192 
    193 :doDebug
    194 shift
    195 set _EXECJAVA=%_RUNJDB%
    196 set DEBUG_OPTS=-sourcepath "%CATALINA_HOME%....java"
    197 if not ""%1"" == ""-security"" goto execCmd
    198 shift
    199 echo Using Security Manager
    200 set "SECURITY_POLICY_FILE=%CATALINA_BASE%confcatalina.policy"
    201 goto execCmd
    202 
    203 :doRun
    204 shift
    205 if not ""%1"" == ""-security"" goto execCmd
    206 shift
    207 echo Using Security Manager
    208 set "SECURITY_POLICY_FILE=%CATALINA_BASE%confcatalina.policy"
    209 goto execCmd
    210 
    211 :doStart
    212 shift
    213 if "%TITLE%" == "" set TITLE=Tomcat
    214 set _EXECJAVA=start "%TITLE%" %_RUNJAVA%
    215 if not ""%1"" == ""-security"" goto execCmd
    216 shift
    217 echo Using Security Manager
    218 set "SECURITY_POLICY_FILE=%CATALINA_BASE%confcatalina.policy"
    219 goto execCmd
    220 
    221 :doStop
    222 shift
    223 set ACTION=stop
    224 set CATALINA_OPTS=
    225 goto execCmd
    226 
    227 :doConfigTest
    228 shift
    229 set ACTION=configtest
    230 set CATALINA_OPTS=
    231 goto execCmd
    232 
    233 :doVersion
    234 %_EXECJAVA% -classpath "%CATALINA_HOME%libcatalina.jar" org.apache.catalina.util.ServerInfo
    235 goto end
    236 
    237 
    238 :execCmd
    239 rem Get remaining unshifted command line arguments and save them in the
    240 set CMD_LINE_ARGS=
    241 :setArgs
    242 if ""%1""=="""" goto doneSetArgs
    243 set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
    244 shift
    245 goto setArgs
    246 :doneSetArgs
    247 
    248 rem Execute Java with the applicable properties
    249 if not "%JPDA%" == "" goto doJpda
    250 if not "%SECURITY_POLICY_FILE%" == "" goto doSecurity
    251 %_EXECJAVA% %LOGGING_CONFIG% %LOGGING_MANAGER% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -D%ENDORSED_PROP%="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
    252 goto end
    253 :doSecurity
    254 %_EXECJAVA% %LOGGING_CONFIG% %LOGGING_MANAGER% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -D%ENDORSED_PROP%="%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%
    255 goto end
    256 :doJpda
    257 if not "%SECURITY_POLICY_FILE%" == "" goto doSecurityJpda
    258 %_EXECJAVA% %LOGGING_CONFIG% %LOGGING_MANAGER% %JAVA_OPTS% %JPDA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -D%ENDORSED_PROP%="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
    259 goto end
    260 :doSecurityJpda
    261 %_EXECJAVA% %LOGGING_CONFIG% %LOGGING_MANAGER% %JAVA_OPTS% %JPDA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -D%ENDORSED_PROP%="%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%
    262 goto end
    263 
    264 :end

    第一段:

     1 rem Suppress Terminate batch job on CTRL+C
     2 if not ""%1"" == ""run"" goto mainEntry
     3 if "%TEMP%" == "" goto mainEntry
     4 if exist "%TEMP%\%~nx0.run" goto mainEntry
     5 echo Y>"%TEMP%\%~nx0.run"
     6 if not exist "%TEMP%\%~nx0.run" goto mainEntry
     7 echo Y>"%TEMP%\%~nx0.Y"
     8 call "%~f0" %* <"%TEMP%\%~nx0.Y"
     9 rem Use provided errorlevel
    10 set RETVAL=%ERRORLEVEL%
    11 del /Q "%TEMP%\%~nx0.Y" >NUL 2>&1
    12 exit /B %RETVAL%
    13 :mainEntry
    14 del /Q "%TEMP%\%~nx0.run" >NUL 2>&1
    1. 首先注释是说,禁止使用 CTRL+C 来终止批处理任务;

    2. if not ""%1"" == ""run"" goto mainEntry,第一个参数不是run,就转向mainEntry标签,通过调用startup.bat启动的第一个参数应该是start;

    3. if "%TEMP%" == "" goto mainEntry,%TEMP%是系统的环境变量值,通常装完windows系统的话, 系统会自动配置上这个环境变量,一般是C:Users用户名AppDataLocalTemp(AppData是一个隐藏文件夹)。这句是说,如果%TEMP%是空串,就转向mainEntry标签;

    4. if exist "%TEMP%\%~nx0.run" goto mainEntry, 在批处理中,%1 表示的是程序之后的第一个参数,%0表示这个可执行程序的名称, %~nx0 的话就是程序的名称+扩展名,在这里就是catalina.bat(可以写一个脚本测试下);

    5. echo Y>"%TEMP%\%~nx0.run",写入字符Y到%TEMP%catalina.bat.run 文件中;

    6. if not exist "%TEMP%\%~nx0.run" goto mainEntry,又判断了一下 %TEMP%catalina.bat.run 文件是否存在;

    7. echo Y>"%TEMP%\%~nx0.Y",写入Y到%TEMP%catalina.bat.Y,如果文件不存在, 则新建一个;

    8. call "%~f0" %* <"%TEMP%\%~nx0.Y",- “%~f0” : 简单说就是表示当前命令的绝对路径。- “%” : %1表示第一个参数,%2表示第二个,%代表所有参数。<”%TEMP%\%~nx0.Y”是读取 %TEMP%catalina.bat.Y文件中的内容,之后又通过call进行调用;

    9. set RETVAL=%ERRORLEVEL%,Windows中和linux一样,命令执行完之后都有自己的退出码,%ERRORLEVEL%就是取的上面的call 命令的退出码,赋值给一个变量RETVAL;

    10. del /Q "%TEMP%\%~nx0.Y" >NUL 2>&1,del 命令,很容易联想到delete, 那么/Q是什么意思呢?静默删除,不会给出任何提示,就比如Linux中的rm -f 一样。这里是删除%TEMP%catalina.bat.Y这个文件。后面的 >NUL 2>&1又是什么意思呢? >NUL : 表示将输出重定向到 NUL 中,你什么也看不到;2>&1 : 2:错误输出,&1: 标准输出, 意思就是将错误消息输出到标准输出中;>NUL 2>&1 : 就是先将错误消息输出到标准输出中,然后再输出到 NUL 中;

    11. exit /B %RETVAL%,退出当前批处理, /B 指定退出时的编号, 把 RETVAL 作为 退出码, 也就是 call 执行的命令的退出码;

    12. :mainEntry del /Q “%TEMP%\%~nx0.run” >NUL 2>&1,定义一个 mainEntry 标签,然后删除临时目录中的 catalina.bat.run 文件。

     这段代码的作用就是调用本身,判断临时目录中的文件是否存在来避免二次回调自己

    第二段:

     1 rem Guess CATALINA_HOME if not defined
     2 set "CURRENT_DIR=%cd%"
     3 if not "%CATALINA_HOME%" == "" goto gotHome
     4 set "CATALINA_HOME=%CURRENT_DIR%"
     5 if exist "%CATALINA_HOME%incatalina.bat" goto okHome
     6 cd ..
     7 set "CATALINA_HOME=%cd%"
     8 cd "%CURRENT_DIR%"
     9 :gotHome
    10 
    11 if exist "%CATALINA_HOME%incatalina.bat" goto okHome
    12 echo The CATALINA_HOME environment variable is not defined correctly
    13 echo This environment variable is needed to run this program
    14 goto end
    15 :okHome
    16 
    17 rem Copy CATALINA_BASE from CATALINA_HOME if not defined
    18 if not "%CATALINA_BASE%" == "" goto gotBase
    19 set "CATALINA_BASE=%CATALINA_HOME%"
    20 :gotBase
    1. set "CURRENT_DIR=%cd%",设置CURRENT_DIR为当前目录bin(假如你是在bin目录中启动);

    2. if not "%CATALINA_HOME%" == "" goto gotHome,CATALINA_HOME不是空就转向gotHome;

    3. set "CATALINA_HOME=%CURRENT_DIR%",设置CATALINA_HOME指向CURRENT_DIR的目录,也就是bin目录;

    4. if exist "%CATALINA_HOME%incatalina.bat" goto okHome,如果存在%CATALINA_HOME%incatalina.bat,那么就转向okHome,否则退出到父目录,(显然不存在binincatalina.bat);

    5. set "CATALINA_HOME=%cd%",设置CATALINA_HOME为当前目录(也就是Tomcat的根目录);

    6. cd "%CURRENT_DIR%",进入CURRENT_HOME指向的目录,也就是bin目录,执行gotHome标签;

    7. if exist "%CATALINA_HOME%incatalina.bat" goto okHome,gotHome标签下,如果存在%CATALINA_HOME%incatalina.bat,就转向okHome,因为CATALINA_HOME现在指向的目录是Tomcat的安装目录,所以incatalina.bat文件是存在的,所以转向okHome标签;

    8. if not "%CATALINA_BASE%" == "" goto gotBase,如果CATALINA_BASE变量不是空,就转向gotBase标签(显然为空);

    9. set "CATALINA_BASE=%CATALINA_HOME%",设置CATALINA_BASE的值等同与CATALINA_HOME的值(现在CATALINA_BASE也指向的Tomcat的根目录了)。

    这段主要是设置了两个环境变量 CATALINA_HOME 和 CATALINA_BASE。如果没有配置 CATALINA_BASE 环境变量的话, 直接引用 CATALINA_HOME 的值。

    第三段:

     1 rem Ensure that neither CATALINA_HOME nor CATALINA_BASE contains a semi-colon
     2 rem as this is used as the separator in the classpath and Java provides no
     3 rem mechanism for escaping if the same character appears in the path. Check this
     4 rem by replacing all occurrences of ';' with '' and checking that neither
     5 rem CATALINA_HOME nor CATALINA_BASE have changed
     6 if "%CATALINA_HOME%" == "%CATALINA_HOME:;=%" goto homeNoSemicolon
     7 echo Using CATALINA_HOME:   "%CATALINA_HOME%"
     8 echo Unable to start as CATALINA_HOME contains a semicolon (;) character
     9 goto end
    10 :homeNoSemicolon
    11 
    12 if "%CATALINA_BASE%" == "%CATALINA_BASE:;=%" goto baseNoSemicolon
    13 echo Using CATALINA_BASE:   "%CATALINA_BASE%"
    14 echo Unable to start as CATALINA_BASE contains a semicolon (;) character
    15 goto end
    16 :baseNoSemicolon

    这里主要是判断 CATALINA_HOME 环境变量的值 和 CATALINA_BASE 环境变量的值是否以分号为结尾,如果以分号为结尾的话,就报错退出。

    第四段:

     1 rem Ensure that any user defined CLASSPATH variables are not used on startup,
     2 rem but allow them to be specified in setenv.bat, in rare case when it is needed.
     3 set CLASSPATH=
     4 
     5 rem Get standard environment variables
     6 if not exist "%CATALINA_BASE%insetenv.bat" goto checkSetenvHome
     7 call "%CATALINA_BASE%insetenv.bat"
     8 goto setenvDone
     9 :checkSetenvHome
    10 if exist "%CATALINA_HOME%insetenv.bat" call "%CATALINA_HOME%insetenv.bat"
    11 :setenvDone
    12 
    13 rem Get standard Java environment variables
    14 if exist "%CATALINA_HOME%insetclasspath.bat" goto okSetclasspath
    15 echo Cannot find "%CATALINA_HOME%insetclasspath.bat"
    16 echo This file is needed to run this program
    17 goto end
    18 :okSetclasspath
    19 call "%CATALINA_HOME%insetclasspath.bat" %1
    20 if errorlevel 1 goto end

    主要是说,如果Tomcat的bin目录下面存在setenv.bat脚本的话(setenv.bat是干什么的?上面的注释说是用户自定义的环境变量,但并不是启动时必须的定义在setenv.bat中),就执行它,通常情况下是没有的,继而又判断setclasspath.bat脚本是否存在,如果不存在的话, 直接报错,停止启动 Tomcat。如果存在的话,就去调用它,并把 第一个参数传进去。

    可以进入setclasspath.bat脚本看下,主要设置了以下几个环境变量:

    • JAVA_HOME
    • JRE_HOME
    • JAVA_ENDORSED_DIRS = %CATALINA_HOME%endorsed
    • _RUNJAVA = %JRE_HOME%injava.exe
    • _RUNJDB = %JAVA_HOME%injdb.exe

    所以这段是设置一个临时环境变量: CLASSPATH。

    第五段:

     1 rem Add on extra jar file to CLASSPATH
     2 rem Note that there are no quotes as we do not want to introduce random
     3 rem quotes into the CLASSPATH
     4 if "%CLASSPATH%" == "" goto emptyClasspath
     5 set "CLASSPATH=%CLASSPATH%;"
     6 :emptyClasspath
     7 set "CLASSPATH=%CLASSPATH%%CATALINA_HOME%inootstrap.jar"
     8 
     9 if not "%CATALINA_TMPDIR%" == "" goto gotTmpdir
    10 set "CATALINA_TMPDIR=%CATALINA_BASE%	emp"
    11 :gotTmpdir
    12 
    13 rem Add tomcat-juli.jar to classpath
    14 rem tomcat-juli.jar can be over-ridden per instance
    15 if not exist "%CATALINA_BASE%in	omcat-juli.jar" goto juliClasspathHome
    16 set "CLASSPATH=%CLASSPATH%;%CATALINA_BASE%in	omcat-juli.jar"
    17 goto juliClasspathDone
    18 :juliClasspathHome
    19 set "CLASSPATH=%CLASSPATH%;%CATALINA_HOME%in	omcat-juli.jar"
    20 :juliClasspathDone

    这段代码主要做了三件事:

    • 把 Tomcat bin 目录下的 bootstrap.jar 加入到环境变量中;
    • 设置 CATALINA_TMPDIR 环境变量的值为 Tomcat 目录下的 temp 目录;
    • 把 Tomcat bin 目录下的 tomcat-juli.jar 加入到环境变量中;

    第六段:

     1 if not "%JSSE_OPTS%" == "" goto gotJsseOpts
     2 set JSSE_OPTS="-Djdk.tls.ephemeralDHKeySize=2048"
     3 :gotJsseOpts
     4 set "JAVA_OPTS=%JAVA_OPTS% %JSSE_OPTS%"
     5 
     6 rem Register custom URL handlers
     7 rem Do this here so custom URL handles (specifically 'war:...') can be used in the security policy
     8 set "JAVA_OPTS=%JAVA_OPTS% -Djava.protocol.handler.pkgs=org.apache.catalina.webresources"
     9 
    10 if not "%LOGGING_CONFIG%" == "" goto noJuliConfig
    11 set LOGGING_CONFIG=-Dnop
    12 if not exist "%CATALINA_BASE%conflogging.properties" goto noJuliConfig
    13 set LOGGING_CONFIG=-Djava.util.logging.config.file="%CATALINA_BASE%conflogging.properties"
    14 :noJuliConfig
    15 
    16 if not "%LOGGING_MANAGER%" == "" goto noJuliManager
    17 set LOGGING_MANAGER=-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
    18 :noJuliManager
    19 
    20 rem Configure JAVA 9 specific start-up parameters
    21 set "JDK_JAVA_OPTIONS=%JDK_JAVA_OPTIONS% --add-opens=java.base/java.lang=ALL-UNNAMED"
    22 set "JDK_JAVA_OPTIONS=%JDK_JAVA_OPTIONS% --add-opens=java.base/java.io=ALL-UNNAMED"
    23 set "JDK_JAVA_OPTIONS=%JDK_JAVA_OPTIONS% --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED"

    主要是追加一系列的启动参数到 JAVA_OPTS 这个环境变量中。

     1 rem Java 9 no longer supports the java.endorsed.dirs
     2 rem system property. Only try to use it if
     3 rem JAVA_ENDORSED_DIRS was explicitly set
     4 rem or CATALINA_HOME/endorsed exists.
     5 set ENDORSED_PROP=ignore.endorsed.dirs
     6 if "%JAVA_ENDORSED_DIRS%" == "" goto noEndorsedVar
     7 set ENDORSED_PROP=java.endorsed.dirs
     8 goto doneEndorsed
     9 :noEndorsedVar
    10 if not exist "%CATALINA_HOME%endorsed" goto doneEndorsed
    11 set ENDORSED_PROP=java.endorsed.dirs
    12 :doneEndorsed

    第七段:

     1 echo Using CATALINA_BASE:   "%CATALINA_BASE%"
     2 echo Using CATALINA_HOME:   "%CATALINA_HOME%"
     3 echo Using CATALINA_TMPDIR: "%CATALINA_TMPDIR%"
     4 if ""%1"" == ""debug"" goto use_jdk
     5 echo Using JRE_HOME:        "%JRE_HOME%"
     6 goto java_dir_displayed
     7 :use_jdk
     8 echo Using JAVA_HOME:       "%JAVA_HOME%"
     9 :java_dir_displayed
    10 echo Using CLASSPATH:       "%CLASSPATH%"

    打印相关的环境变量信息。

    第八段:

    1 set _EXECJAVA=%_RUNJAVA%
    2 set MAINCLASS=org.apache.catalina.startup.Bootstrap
    3 set ACTION=start
    4 set SECURITY_POLICY_FILE=
    5 set DEBUG_OPTS=
    6 set JPDA=

    设置一些环境变量:

    1. _RUNJAVA : %JRE_HOME%injava.exe;

    2. MAINCLASS : 指定了 Tomcat 的启动类;

    3. ACTION : 动作, 就是启动;

    4. SECURITY_POLICY_FILE : 安全策略文件,如果启动的时候加上了 -security 参数的话,下面会对这个参数指定到 Tomcat 的 conf 目录下的 catalina.policy 文件;

    5. JPDA : 还不清楚 。

    第九段:

     1 if not ""%1"" == ""jpda"" goto noJpda
     2 set JPDA=jpda
     3 if not "%JPDA_TRANSPORT%" == "" goto gotJpdaTransport
     4 set JPDA_TRANSPORT=dt_socket
     5 :gotJpdaTransport
     6 if not "%JPDA_ADDRESS%" == "" goto gotJpdaAddress
     7 set JPDA_ADDRESS=localhost:8000
     8 :gotJpdaAddress
     9 if not "%JPDA_SUSPEND%" == "" goto gotJpdaSuspend
    10 set JPDA_SUSPEND=n
    11 :gotJpdaSuspend
    12 if not "%JPDA_OPTS%" == "" goto gotJpdaOpts
    13 set JPDA_OPTS=-agentlib:jdwp=transport=%JPDA_TRANSPORT%,address=%JPDA_ADDRESS%,server=y,suspend=%JPDA_SUSPEND%
    14 :gotJpdaOpts
    15 shift
    16 :noJpda

    好像直接从第一行跳到了最后一行,一般启动的时候没有加 jpda 参数的话, 这里会直接跳过,里面的脚本是关于 JPDA 的设置等。

    第十段:

     1 if ""%1"" == ""debug"" goto doDebug
     2 if ""%1"" == ""run"" goto doRun
     3 if ""%1"" == ""start"" goto doStart
     4 if ""%1"" == ""stop"" goto doStop
     5 if ""%1"" == ""configtest"" goto doConfigTest
     6 if ""%1"" == ""version"" goto doVersion
     7 
     8 echo Usage:  catalina ( commands ... )
     9 echo commands:
    10 echo   debug             Start Catalina in a debugger
    11 echo   debug -security   Debug Catalina with a security manager
    12 echo   jpda start        Start Catalina under JPDA debugger
    13 echo   run               Start Catalina in the current window
    14 echo   run -security     Start in the current window with security manager
    15 echo   start             Start Catalina in a separate window
    16 echo   start -security   Start in a separate window with security manager
    17 echo   stop              Stop Catalina
    18 echo   configtest        Run a basic syntax check on server.xml
    19 echo   version           What version of tomcat are you running?
    20 goto end

    如果用 startup.bat 启动 Tomcat 的话, 这里的 “%1” 的值是 start; 
    如果通过 catalina.bat run 启动 Tomcat 的话,这里的 “%1” 的值是 run;

    第十一段:

     1 :doDebug
     2 shift
     3 set _EXECJAVA=%_RUNJDB%
     4 set DEBUG_OPTS=-sourcepath "%CATALINA_HOME%....java"
     5 if not ""%1"" == ""-security"" goto execCmd
     6 shift
     7 echo Using Security Manager
     8 set "SECURITY_POLICY_FILE=%CATALINA_BASE%confcatalina.policy"
     9 goto execCmd
    10 
    11 :doRun
    12 shift
    13 if not ""%1"" == ""-security"" goto execCmd
    14 shift
    15 echo Using Security Manager
    16 set "SECURITY_POLICY_FILE=%CATALINA_BASE%confcatalina.policy"
    17 goto execCmd
    18 
    19 :doStart
    20 shift
    21 if "%TITLE%" == "" set TITLE=Tomcat
    22 set _EXECJAVA=start "%TITLE%" %_RUNJAVA%
    23 if not ""%1"" == ""-security"" goto execCmd
    24 shift
    25 echo Using Security Manager
    26 set "SECURITY_POLICY_FILE=%CATALINA_BASE%confcatalina.policy"
    27 goto execCmd
    28 
    29 :doStop
    30 shift
    31 set ACTION=stop
    32 set CATALINA_OPTS=
    33 goto execCmd
    34 
    35 :doConfigTest
    36 shift
    37 set ACTION=configtest
    38 set CATALINA_OPTS=
    39 goto execCmd
    40 
    41 :doVersion
    42 %_EXECJAVA% -classpath "%CATALINA_HOME%libcatalina.jar" org.apache.catalina.util.ServerInfo
    43 goto end

    分别对应前面的标签,启动主要涉及doRun和doStart。

    第一个 shift 是把 start 或者 run 参数移除,然后下面 还是利用 “%1” 来取参数, 这时候, 取出来的就是参数列表中的第二个;
    第二个 shift 是把第二个参数移除掉。

    我们再来比较一下 start 和 run 的启动区别.

    如果是 startup.bat 脚本启动的话, 会启动一个新的 cmd 窗口, 并且把 cmd 的 title 设置为 Tomcat。
    如果是 catalina.bat run 启动的话, 不会新建 cmd 窗口, 也不会设置 cmd 的 title。

    最后都跳到了 execCmd 标签处。

    第十二段:

    1 :execCmd
    2 rem Get remaining unshifted command line arguments and save them in the
    3 set CMD_LINE_ARGS=
    4 :setArgs
    5 if ""%1""=="""" goto doneSetArgs
    6 set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
    7 shift
    8 goto setArgs
    9 :doneSetArgs

    这里还是利用 “%1” 来取出启动命令之后的参数, 如果存在, 追加到 CMD_LINE_ARGS 环境变量上,并把这个参数移除。通常情况下,这里是不会有什么参数。

    最后一段:

     1 rem Execute Java with the applicable properties
     2 if not "%JPDA%" == "" goto doJpda
     3 if not "%SECURITY_POLICY_FILE%" == "" goto doSecurity
     4 %_EXECJAVA% %LOGGING_CONFIG% %LOGGING_MANAGER% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -D%ENDORSED_PROP%="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
     5 goto end
     6 :doSecurity
     7 %_EXECJAVA% %LOGGING_CONFIG% %LOGGING_MANAGER% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -D%ENDORSED_PROP%="%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%
     8 goto end
     9 :doJpda
    10 if not "%SECURITY_POLICY_FILE%" == "" goto doSecurityJpda
    11 %_EXECJAVA% %LOGGING_CONFIG% %LOGGING_MANAGER% %JAVA_OPTS% %JPDA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -D%ENDORSED_PROP%="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
    12 goto end
    13 :doSecurityJpda
    14 %_EXECJAVA% %LOGGING_CONFIG% %LOGGING_MANAGER% %JAVA_OPTS% %JPDA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -D%ENDORSED_PROP%="%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%
    15 goto end
    16 
    17 :end

    正常启动,不会有jdpa,也不会有security,所以这大段代码主要是加一些环境变量,然后带上参数去启动org.apache.catalina.startup.Bootstrap的main方法。

    五、总结

    启动tomcat可以双击startup.bat,也可以在命令行直接catalina.bat run,大致的流程是这样:

    1. 首先判断一下用户直接使用 catalina.bat run 来启动 Tocmat;

    2. 设置 CATALINA_HOME 和 CATALINA_BASE 环境变量值;

    3. 验证 CATALINA_HOME 和 CATALINA_BASE 环境变量值的正确性;

    4. 调用 setnv.bat 脚本;

    5. 调用 setclasspath.bat 脚本;

    6. 添加 bootstrap.jar 和 tomcat-juli.jar 到 CLASSPATH 中;

    7. 设置 CATALINA_TMPDIR 临时目录的值为 Tomcat 目录下的 temp;

    8. 追加一系列的参数到 JAVA_OPTS 中;

    9. 整合相关的启动信息,参数;

    10. 启动 Tomcat。

  • 相关阅读:
    lucene 3.0.2 search 各种各样的Query类型
    lucene 3.0.2 中文分词
    java 文件读写
    java 从args[]中赋值和程序直接赋值不一样?
    java 中文转换成Unicode编码和Unicode编码转换成中文
    Java栈与堆一篇好文
    lucene 3.0.2 操作进阶
    Lucene实战(第2版)》
    java工程包的命名(-dev.jar,-javadoc.jar,jar)
    POJ 3304 Segments (线段和直线相交 + 思维)
  • 原文地址:https://www.cnblogs.com/grasp/p/10029871.html
Copyright © 2020-2023  润新知