日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java bat 启动脚本_解析Tomcat的启动脚本--catalina.bat

發布時間:2024/9/30 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java bat 启动脚本_解析Tomcat的启动脚本--catalina.bat 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

概述

Tomcat 的三個最重要的啟動腳本:

startup.bat

catalina.bat

setclasspath.bat

上一篇咱們分析了 startup.bat 腳本

這一篇咱們來分析 catalina.bat 腳本.

至于 setclasspath.bat 這個腳本, 相信看完這一篇, 就可以自己看懂這個腳本了.

可以點擊下載 [ setclasspath.bat 腳本 ]查看附注釋的 setclasspath.bat 腳本

catalina.bat

這個腳本的代碼有點多, 就單獨弄了一篇展示 catalina.bat 腳本中的內容. 點擊 [catalina.bat 腳本 ]下載查看.

下面咱們就按照腳本中的內容一行行的來分析.

@echo off

setlocal

第一塊腳本代碼

rem Suppress Terminate batch job on CTRL+C

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" %*

rem Use provided errorlevel

set RETVAL=%ERRORLEVEL%

del /Q "%TEMP%\%~nx0.Y" >NUL 2>&1

exit /B %RETVAL%

:mainEntry

del /Q "%TEMP%\%~nx0.run" >NUL 2>&1

腳本的作用

判斷用戶是否使用

catalina.bat run

來啟動 Tomcat 的.

如果用戶使用 startup.bat 腳本啟動 Tomcat, 那么這段腳本不會被執行.

這段代碼看起來很亂, 慢慢分析.

第一行:

注釋, 意思就是: 禁止使用 CTRL+C 來終止批處理任務, 也不知道是怎么禁止的.

第二行:

if not ""%1"" == ""run"" goto mainEntry

首先明白這里的這個 "%1" 這個變量代表的是什么? 正常情況下, 這個腳本是被 startup.bat 腳本調用的, 被調用的同時傳遞了一個 start 參數過來(上一篇分析得出的). 在 批處理命令 中 %1 就表示命令之后的第一個參數, 在這里指的就是 start. 所以 "%1" = start. 如果用戶用 catalina.bat run 命令啟動 Tomcat 的話, 那么這里的 "%1" = run.

第三行:

if "%TEMP%" == "" goto mainEntry

這里的 %TEMP% 很有可能被認為是 空, 其實這里可以讀取到系統的環境變量. 所以, 這里的 %TEMP% 就是系統的環境變量值, 通常裝完 windows 系統的話, 系統會自動配置上這個環境變量. 所以這里一般是有值的. 大家可以去系統的環境變量看一下它指向那個目錄, 一般就是 C:\Users\用戶名\AppData\Local\Temp. 注意: AppData 是一個隱藏目錄.

第四行:

if exist "%TEMP%\%~nx0.run" goto mainEntry

這里又出現了一個新的東西 %~nx0 . 在批處理中, 我們知道 %1 表示的是程序之后的第一個參數, 那么 %0 呢? %0 表示這個可執行程序的名稱, %~nx0 的話就是程序的名稱+擴展名

在這里就是 catalina.bat . 大家可以寫一個小腳本(test.bat)驗證一下: (我的腳本放在 D 盤下)

腳本內容:

@echo off

echo "%~nx0"

echo "%1"

執行結果:

PS D:\> .\test.bat Hello

"test.bat"

"Hello"

PS D:\>

第五行:

echo Y>"%TEMP%\%~nx0.run"

這段代碼很簡單, 就是寫入字符 Y 到 %TEMP%\catalina.bat.run 文件中.

第六行:

if not exist "%TEMP%\%~nx0.run" goto mainEntry

又判斷了一下 %TEMP%\catalina.bat.run 文件是否存在.

第七行:

echo Y>"%TEMP%\%~nx0.Y"

同第五行, 寫入 Y 到 %TEMP%\catalina.bat.Y . 如果文件不存在, 則新建一個.

第八行:

call "%~f0" %*

這一行有點意思. 又出現了兩個新的東西:

(因為 markdown 語法限制, 把下面代碼寫到代碼塊里)

- "%~f0" : 簡單說就是表示當前命令的絕對路徑.

- "%*" : 我們知道 %1 表示第一個參數, 依次類推, %2 表示第二個.... 那么 %* 就很好理解了, 代表所有參數.

驗證一下

腳本內容:

@echo off

echo "%*"

echo "%~f0"

執行結果:

PS D:\> .\test.bat Hello World

"Hello World"

"D:\test.bat"

PS D:\>

那么后面的

之后又通過 call 進行調用.

我們自己寫一個例子, 在 D 盤建立 test.bat 文件, 再建立 catalina.bat.Y 文件

腳本內容:

call "%~f0" %* < D:/catalina.bat.Y

catalina.bat.Y 文件內容

Y

執行結果:

........

D:\>call "D:\test.bat" Hello World 0

D:\>call "D:\test.bat" Hello World 0

D:\>call "D:\test.bat" Hello World 0

D:\>call "D:\test.bat" Hello World 0

D:\>call "D:\test.bat" Hello World 0

D:\>call "D:\test.bat" Hello World 0

D:\>call "D:\test.bat" Hello World 0

****** 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 ******

最上面省略了很多重復代碼, 從這里發現它不斷地調用自己本身, 直到超出了堆棧的限制才停止.

我們如果加上 @echo off 的話

@echo off

call "%~f0" %* < D:/catalina.bat.Y

結果只會出現

D:\>.\test.bat 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 ******

我們這里只需要明白這些命令的作用就可以, 稍后我們會總結 Tomcat 執行這些命令的目的.

第十行:

set RETVAL=%ERRORLEVEL%

我們如果了解 Linux 的話都知道, 每個命令的執行都會返回一個執行完成之后的退出碼. Linux執行完一條命令之后用 echo $? 來查看上一條命令的退出碼. 在 Windows 中也是一樣的, 命令執行完之后都有自己的退出碼. 這里的 %ERRORLEVEL% 就是取的上面的 call 命令的退出碼. 賦值給一個變量 RETVAL

第十一行:

del /Q "%TEMP%\%~nx0.Y" >NUL 2>&1

這里又出現了一個 del 命令, 很容易聯想到 delete, 那么 /Q 是什么意思呢? 靜默刪除, 不會給你任何提示, 就比如 Linux 中的 rm -f 一樣, 這里是刪除 %TEMP%\catalina.bat.Y 這個文件.

后面的 >NUL 2>&1 又是什么意思呢?

于 Linux 中的輸出流的重定向原理是一樣的.

(因為 markdown 語法限制, 把下面代碼寫到代碼塊里)

- >NUL : 表示將輸出重定向到 NUL 中, 你什么也看不到

- 2>&1 : 2:錯誤輸出, &1: 標準輸出, 意思就是將錯誤消息輸出到標準輸出中.

- >NUL 2>&1 : 就是先將錯誤消息輸出到標準輸出中, 然后再輸出到 NUL 中.

第十二行:

exit /B %RETVAL%

退出當前批處理, /B 指定退出時的編號, 把 RETVAL 最為 退出碼, 也就是 call 執行的命令 的退出碼.

最后兩行:

:mainEntry

del /Q "%TEMP%\%~nx0.run" >NUL 2>&1

定義一個 mainEntry 標簽, 然后刪除 臨時目錄中的 catalina.bat.run 文件.

總結第一段腳本的功能

簡單說, 這段代碼的作用就是調用本身, 判斷臨時目錄中的文件是否存在來避免二次回調自己. 感覺寫的好復雜.

下面就進入 Tomcat 的正式啟動過程, 并沒有開始執行 main 方法

第二段腳本代碼

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\catalina.bat" goto okHome

cd ..

set "CATALINA_HOME=%cd%"

cd "%CURRENT_DIR%"

:gotHome

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

set "CATALINA_BASE=%CATALINA_HOME%"

:gotBase

這段腳本還是比較簡單的, 主要是設置了兩個環境變量 CATALINA_HOME 和 CATALINA_BASE .

如果沒有配置 CATALINA_BASE 環境變量的話, 直接引用 CATALINA_HOME 的值

靜下心來稍微看一下就懂了.

第三段腳本代碼

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

這里主要是判斷 CATALINA_HOME 環境變量的值 和 CATALINA_BASE 環境變量的值是否以 分號為結尾, 如果以 分號為結尾的話, 就報錯退出.

第四段腳本代碼

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=

rem Get standard environment variables

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

rem Get standard Java environment variables

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

call "%CATALINA_HOME%\bin\setclasspath.bat" %1

if errorlevel 1 goto end

設置一個臨時環境變量: CLASSPATH.

如果 Tomcat 的 bin 目錄下面存在 setnv.bat 腳本的話, 就執行它. 通常情況下是沒有的.

繼而又判斷 setclasspath.bat 腳本是否存在, 如果不存在的話, 直接報錯, 停止啟動 Tomcat.

如果存在的話, 就去調用它, 并把 第一個參數傳進去.

setclasspath.bat 這個腳本主要設置了幾個環境變量

JAVA_HOME

JRE_HOME

JAVA_ENDORSED_DIRS = %CATALINA_HOME%\endorsed

_RUNJAVA = %JRE_HOME%\bin\java.exe

_RUNJDB = %JAVA_HOME%\bin\jdb.exe

第五段腳本代碼

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\bootstrap.jar"

if not "%CATALINA_TMPDIR%" == "" goto gotTmpdir

set "CATALINA_TMPDIR=%CATALINA_BASE%\temp"

: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

set "CLASSPATH=%CLASSPATH%;%CATALINA_BASE%\bin\tomcat-juli.jar"

goto juliClasspathDone

:juliClasspathHome

set "CLASSPATH=%CLASSPATH%;%CATALINA_HOME%\bin\tomcat-juli.jar"

:juliClasspathDone

這段代碼主要做了三件事:

把 Tomcat bin 目錄下的 bootstrap.jar 加入到環境變量中

設置 CATALINA_TMPDIR 環境變量的值為 Tomcat 目錄下的 temp 目錄

把 Tomcat bin 目錄下的 tomcat-juli.jar 加入到環境變量中

第六段腳本代碼

if not "%JSSE_OPTS%" == "" goto gotJsseOpts

set JSSE_OPTS="-Djdk.tls.ephemeralDHKeySize=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% -Djava.protocol.handler.pkgs=org.apache.catalina.webresources"

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%"

主要是追加一系列的啟動參數到 JAVA_OPTS 這個環境變量中.

第八段腳本代碼

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%"

主要是打印相關的環境變量信息.

第九段腳本代碼

set _EXECJAVA=%_RUNJAVA%

set MAINCLASS=org.apache.catalina.startup.Bootstrap

set ACTION=start

set SECURITY_POLICY_FILE=

set DEBUG_OPTS=

set JPDA=

設置一些列的環境變量:

_RUNJAVA : %JRE_HOME%\bin\java.exe

MAINCLASS : 指定了 Tomcat 的啟動類, 沒錯 main 方法就是在這個類里面.

ACTION : 動作: 就是啟動

SECURITY_POLICY_FILE : 安全策略文件, 如果啟動的時候加上了 -security 參數的話, 下面會對這個參數指定到 Tomcat 的 conf 目錄下的 catalina.policy 文件.

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=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

好像直接從第一行跳到了最后一行, 沒錯, 一般我沒啟動的時候沒有加 jpda 參數的話, 這里會直接跳過, 里面的腳本是關于 JPDA 的設置等.

第十一段腳本代碼

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

好似一個 switch 開關.

如果我們用 startup.bat 啟動 Tomcat 的話, 這里的 "%1" 的值是 start

如果通過 catalina.bat run 啟動 Tomcat 的話, 這里的 "%1" 的值是 run

第十二段腳本代碼

:doRun

shift

if not ""%1"" == ""-security"" goto execCmd

shift

echo Using Security Manager

set "SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy"

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\catalina.policy"

goto execCmd

首先分析一下其中的兩個 shift 命令

第一個 shift 是把 start 或者 run 參數移除, 然后下面 還是利用 "%1" 來取參數, 這時候, 取出來的就是參數列表中的第二個.

第二個 shift 是在第二個參數移除掉.

我們再來比較一下 start 和 run 的啟動區別.

差別

if "%TITLE%" == "" set TITLE=Tomcat

set _EXECJAVA=start "%TITLE%" %_RUNJAVA%

如果是 startup.bat 腳本啟動的話, 會啟動一個新的 cmd 窗口, 并且把 cmd 的 title 設置為 Tomcat.

如果是 catalina.bat run 啟動的話, 不會新建 cmd 窗口, 也不會設置 cmd 的 title.

最后都跳到了 execCmd 標簽處.

第十三段腳本代碼

: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

這里還是利用 "%1" 來取出啟動命令之后的參數, 如果存的話, 追加到 CMD_LINE_ARGS 環境變量上, 并把這個參數移除.

通常情況下, 我們這里是不會有什么參數了, -security 這個參數我們都不會追加.

繼續往下走.

第十四段腳本代碼

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%

goto end

很明顯, 我們的 %JPDA% 沒有值, 不會跳轉; 由于我們沒有加 -security 參數, 所以 %SECURITY_POLICY_FILE% 沒有值, 不會跳轉.

下面這段長命令就是來啟動 BootStrap 類, 并把相應的參數傳進去.

只要把對應的環境變量替換為它們的值, 就可以解析出這個長命令的內容. 相信你可以的. Be patient!

總結一下

首先判斷一下用戶直接使用 catalina.bat run 來啟動 Tocmat

設置 CATALINA_HOME 和 CATALINA_BASE 環境變量值

驗證 CATALINA_HOME 和 CATALINA_BASE 環境變量值的正確性

調用 setnv.bat 腳本

調用 setclasspath.bat 腳本

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

設置 CATALINA_TMPDIR 臨時目錄的值為 Tomcat 目錄下的 temp

追加一系列的參數到 JAVA_OPTS 中

整合相關的啟動信息, 參數

啟動 Tomcat

以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,有興趣的朋友可以看下上篇文章《解析Tomcat的啟動腳本-startup.bat》

總結

以上是生活随笔為你收集整理的java bat 启动脚本_解析Tomcat的启动脚本--catalina.bat的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。