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

2019-10-18 15:49:15于丽

脚本内容:

@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" %* <"%TEMP%%~nx0.Y"

这一行有点意思. 又出现了两个新的东西:

(因为 markdown 语法限制, 把下面代码写到代码块里)

- "%~f0" : 简单说就是表示当前命令的绝对路径.
- "%*" : 我们知道 %1 表示第一个参数, 依次类推, %2 表示第二个.... 那么 %* 就很好理解了, 代表所有参数.

验证一下

脚本内容:

@echo off
echo "%*"
echo "%~f0"

执行结果:

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

那么后面的 <"%TEMP%%~nx0.Y" 意思就是读取 %TEMP%catalina.bat.Y 文件中的内容.

之后又通过 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:/catalina.bat.Y
D:>call "D:test.bat" Hello World 0<D:/catalina.bat.Y
D:>call "D:test.bat" Hello World 0<D:/catalina.bat.Y
D:>call "D:test.bat" Hello World 0<D:/catalina.bat.Y
D:>call "D:test.bat" Hello World 0<D:/catalina.bat.Y
D:>call "D:test.bat" Hello World 0<D:/catalina.bat.Y
D:>call "D:test.bat" Hello World 0<D:/catalina.bat.Y
****** 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