Overview
The three most important startup scripts for Tomcat:
Previous articleWe analyzed the script
Let's analyze the script in this article.
As for this script, I believe that after reading this article, I can understand this script by myself.
You can click to download [script]View the commented script
There is a lot of code in this script, so I made a separate article to display the contents in the script. Click [script]Download to view.
Let’s analyze it line by line according to the content in the script.
@echo off setlocal
These two commands can be found in the previous article (Parse Tomcat's startup script--) Explanation
The first script code
rem Suppress Terminate batch job on CTRL+C if not ""%1"" == ""run"" goto mainEntry if "%TEMP%" == "" goto mainEntry if exist "%TEMP%\%~" goto mainEntry echo Y>"%TEMP%\%~" if not exist "%TEMP%\%~" goto mainEntry echo Y>"%TEMP%\%~" call "%~f0" %* <"%TEMP%\%~" rem Use provided errorlevel set RETVAL=%ERRORLEVEL% del /Q "%TEMP%\%~" >NUL 2>&1 exit /B %RETVAL% :mainEntry del /Q "%TEMP%\%~" >NUL 2>&1
The role of scripts
Determine whether the user is using it
run
To start Tomcat.
If the user starts Tomcat with a script, the script will not be executed.
This code looks messy, so analyze it slowly.
First line:
Comments, meaning: CTRL+C is prohibited from using CTRL+C to terminate batch tasks, and I don’t know how it is prohibited.
Line 2:
if not ""%1"" == ""run"" goto mainEntry
First of all, understand what the "%1" variable here represents? Under normal circumstances, this script is called by a script, and when it is called, a start parameter is passed (derived from the previous analysis). In the batch command, %1 represents the first parameter after the command, which refers to start here. So "%1" = start. If the user starts Tomcat with the run command, then "%1" = run here.
Line 3:
if "%TEMP%" == "" goto mainEntry
The %TEMP% here is likely to be considered empty, but in fact, the system's environment variable can be read here. Therefore, the %TEMP% here is the system's environment variable value. Usually, after installing the Windows system, the system will automatically configure this environment variable. So there are usually values here. You can go to the system's environment variable to see which directory it points to, which is generally C:\Users\username\AppData\Local\Temp. Note: AppData is a hidden directory.
Line 4:
if exist "%TEMP%\%~" goto mainEntry
Here is another new thing %~nx0. In batch processing, we know that %1 represents the first parameter after the program, so what about %0? %0 represents the name of this executable program. If %~nx0 is the name of the program + the extension
Here is it. You can write a small script () to verify it: (My script is placed under D disk)
Script content:
@echo off echo "%~nx0" echo "%1"
Execution results:
PS D:\> .\ Hello "" "Hello" PS D:\>
The fifth element:
echo Y>"%TEMP%\%~"
This code is very simple, it is to write the character Y into the %TEMP%\ file.
Line 6:
if not exist "%TEMP%\%~" goto mainEntry
I also judged whether the %TEMP%\ file exists.
Line 7:
echo Y>"%TEMP%\%~"
In the same fifth line, write Y to %TEMP%\. If the file does not exist, create a new one.
Line 8:
call "%~f0" %* <"%TEMP%\%~"
This line is interesting. Two new things have appeared:
(Because of the markdown syntax limitation, write the following code into the code block)
- "%~f0" : Simply put, it means the absolute path of the current command.
- "%*" : We know that %1 represents the first parameter, and so on, %2 represents the second... Then %* is easy to understand, representing all parameters.
Verify
Script content:
@echo off echo "%*" echo "%~f0"
Execution results:
PS D:\> .\ Hello World "Hello World" "D:\" PS D:\>
Then the following <"%TEMP%\%~" means reading the contents in the %TEMP%\ file.
Then it is called through call.
Let's write an example ourselves, create a file on disk D, and then create a file
Script content:
call "%~f0" %* < D:/
File content
Y
Execution results:
........ D:\>call "D:\" Hello World 0<D:/ D:\>call "D:\" Hello World 0<D:/ D:\>call "D:\" Hello World 0<D:/ D:\>call "D:\" Hello World 0<D:/ D:\>call "D:\" Hello World 0<D:/ D:\>call "D:\" Hello World 0<D:/ D:\>call "D:\" Hello World 0<D:/ ****** B A T C H R E C U R S I O N exceeds STACK limits ****** Recursion Count=593, Stack Usage=90 percent ****** B A T C H PROCESSING IS A B O R T E D ******
A lot of duplicate code is omitted at the top, and from here it finds that it keeps calling itself until it exceeds the limit of the stack.
If we add @echo off
@echo off call "%~f0" %* < D:/
The result will only appear
D:\>.\ Hello World ****** B A T C H R E C U R S I O N exceeds STACK limits ****** Recursion Count=593, Stack Usage=90 percent ****** B A T C H PROCESSING IS A B O R T E D ******
We only need to understand the role of these commands here. We will summarize the purpose of Tomcat's execution of these commands later.
Line 10:
set RETVAL=%ERRORLEVEL%
If we know Linux, we all know that the execution of each command will return an exit code after execution. After Linux executes a command, use echo $? to view the exit code of the previous command. The same is true in Windows, and the command has its own exit code after execution. The %ERRORLEVEL% here is the exit code of the call command above. Assign it to a variable RETVAL
Line 11:
del /Q "%TEMP%\%~" >NUL 2>&1
Another del command appears here, which is easy to associate with delete. So what does /Q mean? Silent deletion will not give you any prompts, just like rm -f in Linux, here is to delete the %TEMP%\ file.
What does the following >NUL 2>&1 mean?
The principle of redirecting the output stream in Linux is the same.
(Because of the markdown syntax limitation, write the following code into the code block)
- >NUL : Indicates redirecting the output to NUL middle, You can't see anything - 2>&1 : 2:Error output, &1: Standard output, 意思就是将错误消息输出到Standard outputmiddle. - >NUL 2>&1 : 就是先将错误消息输出到Standard outputmiddle, Then output to NUL middle.
Line 12:
exit /B %RETVAL%
Exit the current batch process, /B specifies the number at the time of exit, and sets the RETVAL most exit code, which is the exit code of the command executed by call.
The last two lines:
:mainEntry del /Q "%TEMP%\%~" >NUL 2>&1
Define a mainEntry tag and then delete the files in the temporary directory.
Summarize the functions of the first script
Simply put, the function of this code is to call itself, to judge whether the files in the temporary directory exist to avoid the secondary callback itself. It feels like the writing is very complicated.
Let’s enter the official startup process of Tomcat, and the main method is not started.
The second script code
rem Guess CATALINA_HOME if not defined set "CURRENT_DIR=%cd%" if not "%CATALINA_HOME%" == "" goto gotHome set "CATALINA_HOME=%CURRENT_DIR%" if exist "%CATALINA_HOME%\bin\" goto okHome cd .. set "CATALINA_HOME=%cd%" cd "%CURRENT_DIR%" :gotHome if exist "%CATALINA_HOME%\bin\" 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 set "CATALINA_BASE=%CATALINA_HOME%" :gotBase
This script is relatively simple, mainly setting two environment variables: CATALINA_HOME and CATALINA_BASE.
If the CATALINA_BASE environment variable is not configured, directly refer to the value of CATALINA_HOME
Calm down and take a look at it and you will understand.
The third script code
rem Ensure that neither CATALINA_HOME nor CATALINA_BASE contains a semi-colon rem as this is used as the separator in the classpath and Java provides no rem mechanism for escaping if the same character appears in the path. Check this rem by replacing all occurrences of ';' with '' and checking that neither rem CATALINA_HOME nor CATALINA_BASE have changed 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 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
Here we mainly judge whether the values of the CATALINA_HOME environment variable and the values of the CATALINA_BASE environment variable end with a semicolon. If they end with a semicolon, an error will be reported and exited.
Fourth script code
rem Ensure that any user defined CLASSPATH variables are not used on startup, rem but allow them to be specified in , in rare case when it is needed. set CLASSPATH= rem Get standard environment variables if not exist "%CATALINA_BASE%\bin\" goto checkSetenvHome call "%CATALINA_BASE%\bin\" goto setenvDone :checkSetenvHome if exist "%CATALINA_HOME%\bin\" call "%CATALINA_HOME%\bin\" :setenvDone rem Get standard Java environment variables if exist "%CATALINA_HOME%\bin\" goto okSetclasspath echo Cannot find "%CATALINA_HOME%\bin\" echo This file is needed to run this program goto end :okSetclasspath call "%CATALINA_HOME%\bin\" %1 if errorlevel 1 goto end
Set a temporary environment variable: CLASSPATH.
If a script exists under the bin directory of Tomcat, execute it. Usually there is no.
Then we will determine whether the script exists. If it does not exist, an error will be reported directly and the Tomcat will be stopped.
If it exists, call it and pass the first parameter in.
This script mainly sets several environment variables
- JAVA_HOME
- JRE_HOME
- JAVA_ENDORSED_DIRS = %CATALINA_HOME%\endorsed
- _RUNJAVA = %JRE_HOME%\bin\
- _RUNJDB = %JAVA_HOME%\bin\
The fifth script code
rem Add on extra jar file to CLASSPATH rem Note that there are no quotes as we do not want to introduce random rem quotes into the CLASSPATH if "%CLASSPATH%" == "" goto emptyClasspath set "CLASSPATH=%CLASSPATH%;" :emptyClasspath set "CLASSPATH=%CLASSPATH%%CATALINA_HOME%\bin\" if not "%CATALINA_TMPDIR%" == "" goto gotTmpdir set "CATALINA_TMPDIR=%CATALINA_BASE%\temp" :gotTmpdir rem Add to classpath rem can be over-ridden per instance if not exist "%CATALINA_BASE%\bin\" goto juliClasspathHome set "CLASSPATH=%CLASSPATH%;%CATALINA_BASE%\bin\" goto juliClasspathDone :juliClasspathHome set "CLASSPATH=%CLASSPATH%;%CATALINA_HOME%\bin\" :juliClasspathDone
This code mainly does three things:
- Add the Tomcat bin directory to the environment variable
- Set the value of the CATALINA_TMPDIR environment variable to the temp directory under the Tomcat directory
- Add the Tomcat bin directory to the environment variable
Sixth script code
if not "%JSSE_OPTS%" == "" goto gotJsseOpts set JSSE_OPTS="-=2048" :gotJsseOpts set "JAVA_OPTS=%JAVA_OPTS% %JSSE_OPTS%" rem Register custom URL handlers rem Do this here so custom URL handles (specifically 'war:...') can be used in the security policy set "JAVA_OPTS=%JAVA_OPTS% -=" if not "%LOGGING_CONFIG%" == "" goto noJuliConfig set LOGGING_CONFIG=-Dnop if not exist "%CATALINA_BASE%\conf\" goto noJuliConfig set LOGGING_CONFIG=-="%CATALINA_BASE%\conf\" :noJuliConfig set "JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG%" if not "%LOGGING_MANAGER%" == "" goto noJuliManager set LOGGING_MANAGER=-= :noJuliManager set "JAVA_OPTS=%JAVA_OPTS% %LOGGING_MANAGER%"
It mainly adds a series of startup parameters to the JAVA_OPTS environment variable.
Eighth script code
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 :use_jdk echo Using JAVA_HOME: "%JAVA_HOME%" :java_dir_displayed echo Using CLASSPATH: "%CLASSPATH%"
It mainly prints relevant environment variable information.
The ninth script code
set _EXECJAVA=%_RUNJAVA% set MAINCLASS= set ACTION=start set SECURITY_POLICY_FILE= set DEBUG_OPTS= set JPDA=
Set some columns of environment variables:
- _RUNJAVA : %JRE_HOME%\bin\
- MAINCLASS: Specifies the startup class of Tomcat. Yes, the main method is in this class.
- ACTION: Action: It is to start
- SECURITY_POLICY_FILE: Security policy file. If the -security parameter is added at startup, the following will specify this parameter to the file in the conf directory of Tomcat.
- JPDA: This parameter can be used on Baidu, but we can hardly use it normally.
The tenth code
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=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 :noJpda
It seems that I jumped directly from the first line to the last line. Yes, usually if I don’t add jpda parameters when I didn’t start, I will skip it directly here. The scripts inside are about JPDA settings, etc.
11 script code
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 echo version What version of tomcat are you running? goto end
It's like a switch switch.
- If we start Tomcat with
- If Tomcat is started with run, the value of "%1" here is run
12th script code
:doRun shift if not ""%1"" == ""-security"" goto execCmd shift echo Using Security Manager set "SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\" goto execCmd :doStart shift if "%TITLE%" == "" set TITLE=Tomcat set _EXECJAVA=start "%TITLE%" %_RUNJAVA% if not ""%1"" == ""-security"" goto execCmd shift echo Using Security Manager set "SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\" goto execCmd
First, analyze two of the shift commands
The first shift removes the start or run parameters, and then uses "%1" to get the parameters. At this time, the second one in the parameter list is taken.
The second shift is removed in the second parameter.
Let's compare the differences between start and run.
difference
if "%TITLE%" == "" set TITLE=Tomcat set _EXECJAVA=start "%TITLE%" %_RUNJAVA%
- If the script is started, a new cmd window will be started and the cmd title is set to Tomcat.
- If run starts, the cmd window will not be created, nor will the cmd title be set.
Finally, they all jumped to the execCmd tag.
Thirteenth script code
:execCmd rem Get remaining unshifted command line arguments and save them in the set CMD_LINE_ARGS= :setArgs if ""%1""=="""" goto doneSetArgs set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1 shift goto setArgs :doneSetArgs
Here we use "%1" to retrieve the parameters after the startup command. If stored, add them to the CMD_LINE_ARGS environment variable and remove this parameter.
Normally, we will not have any parameters here, and we will not append the -security parameter.
Keep going down.
Fourteenth script code
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% -="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -="%CATALINA_BASE%" -="%CATALINA_HOME%" -="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION% goto end
Obviously, our %JPDA% has no value and will not jump; since we did not add the -security parameter, %SECURITY_POLICY_FILE% has no value and will not jump.
The following long command is to start the BootStrap class and pass the corresponding parameters in.
Just replace the corresponding environment variables with their values and parse the content of this long command. I believe you can. Be patient!
Let's summarize
- First, let’s judge that the user directly uses run to start Tocmat
- Set the CATALINA_HOME and CATALINA_BASE environment variable values
- Verify the correctness of the CATALINA_HOME and CATALINA_BASE environment variable values
- Call script
- Call script
- Add and to CLASSPATH
- Set the value of the CATALINA_TMPDIR temporary directory to temp in the Tomcat directory
- Append a series of parameters to JAVA_OPTS
- Integrate relevant startup information, parameters
- Start Tomcat
The above is the entire content of this article. I hope that the content of this article will be of certain help to everyone's study or work. Friends who are interested can read the previous article "Parse Tomcat's startup script-》