1. 程式人生 > >tomcat啟動批處理——catalina.bat

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。

將以上的變數值組裝成一個命令列就是最終啟動的指令碼了。