[Tomcat 源码分析系列] (一) : Tomcat 启动脚本-startup.bat
概述
我们通常使用 Tomcat 中的 startup.bat 来启动 Tomcat. 但是这其中干了一些什么事呢?
大家都知道一个 Java 程序需要启动的话, 肯定需要 main 方法, 那么这个 main 方法在哪呢?
Tomcat 脚本中又是配置了一些什么参数呢, 什么情况下 Tomcat 会启动失败呢?
带着一些列的疑问我们来分析 Tomcat 的三个最重要的启动脚本:
- startup.bat
- catalina.bat
- setclasspath.bat
startup.bat 脚本
该脚本主要做了以下几件事:
- 设置 CATALINA_HOME 环境变量的值
- 找到 catalina.bat 脚本
- 调用 catalina.bat 脚本, 并把参数传过去
贴出简化版本的 startup.bat 脚本的内容
@echo off
rem 执行这个命令之后, 增加或者改动的环境变量只限于匹配到 endlocal 命令或者到达文件末尾.
setlocal
rem 假设 CATALINA_HOME 环境变量没有定义
rem 取当前目录的路径值, 赋给 CURRENT_DIR 变量, 就是 ./apache-tomcat-x.x.xx/bin
set "CURRENT_DIR=%cd%"
rem 如果 CATALINA_HOME 变量值不是 "" 的话, 调到 gotHome 标签处
if not "%CATALINA_HOME%" == "" goto gotHome
rem 如果 CATALINA_HOME 是 "" 的话, 设置 CATALINA_HOME 变量值为 当前目录的路径值(./apache-tomcat-x.x.xx/bin)
set "CATALINA_HOME=%CURRENT_DIR%"
rem 判断当前路径下的是否有 bin\catalina.bat, 也就是 ./apache-tomcat-x.x.xx/bin/bin/catalina.bat
rem 如果存在的话, 直接调到 okHome 标签处, 显然是不存在的
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome
rem 不存在的话, CATALINA_HOME 取上级目录的值, 也就是(./apache-tomcat-x.x.xx/)
cd ..
set "CATALINA_HOME=%cd%"
rem 进入 CURRENT_DIR(./apache-tomcat-x.x.xx/bin)
cd "%CURRENT_DIR%"
:gotHome
rem 通过上面的设置, CATALINA_HOME 的值已经是: ./apache-tomcat-x.x.xx/
rem 所以整理是可以找到 catalina.bat 脚本的, 直接调到 okHome 标签处
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 设置 EXECUTABLE 变量指向为 catalina.bat 脚本
set "EXECUTABLE=%CATALINA_HOME%\bin\catalina.bat"
rem 检查目标可执行文件(catalina.bat)是否存在, 通常情况下是存在的, 直接调到 okExec 标签处
rem 如果不存在的话, 直接退出. 启动 Tomcat 结束
if exist "%EXECUTABLE%" goto okExec
echo Cannot find "%EXECUTABLE%"
echo This file is needed to run this program
goto end
:okExec
rem 获取剩余的没有用 shift 取出来的命令行参数, 并保存它们在 CMD_LINE_ARGS
set CMD_LINE_ARGS=
:setArgs
rem 如果第一个命令行参数是空的话, 跳到 doneSetArgs 标签处
rem "%1" : 表示执行命令之后的第一个参数
if ""%1""=="""" goto doneSetArgs
rem 第一个参数不是空的话, 拼接到 CMD_LINE_ARGS 变量
set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
rem 这个命令可以自行百度
shift
goto setArgs
:doneSetArgs
rem 上面设置了 EXECUTABLE 变量的值是指向了 catalina.bat 脚本, 这个利用 call 命令执行调用, 并把参数传进去
rem 接下来, 咱们看 catalina.bat 脚本的内容
rem 完整的命令: ./apache-tomcat-x.x.xx/bin/catalina.bat start
call "%EXECUTABLE%" start %CMD_LINE_ARGS%
:end
要想理解脚本中的一些命令, 首先来了解一下常用的命令(我们用的 Window 版的)
- rem : 该命令后的代码不会被执行, 相当于注释
- @echo off : 关闭命令的显示, 如果没有设置, 执行了哪些命令都会显示出来
- echo : 输出后面的内容
- setlocal : 执行这个命令之后, 增加或者改动的环境变量的作用范围只限于匹配到 endlocal 命令或者到达文件末尾.
- set : 设置一个变量
- :xxx : 定义一个标签
- goto : 跳转到制定的标签处
- call : 执行命令
我们来一行行分析 startup.bat 脚本
set "CURRENT_DIR=%cd%"
%cd% : 表示文件所在的目录的路径
如果我们解压的 Tomcat 所在的目录为 D:/apache-tomcat-x.x.x/ . 因为 startup.bat 命令在 bin 目录下, 所以此时 %cd% 表示的目录是 D:/apache-tomcat-x.x.x/bin
if not "%CATALINA_HOME%" == "" goto gotHome
我们通常情况下不会配置 CATALINA_HOME 这个环境变量的, 所以这里不会调到 gotHome 标签处.
set "CATALINA_HOME=%CURRENT_DIR%"
直接把当前目录假设为 CATALINA_HOME 的值
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome
然后通过固定的格式来判断一下是否有 catalina.bat 脚本, 当然这里是肯定不会存在的, 因为 CATALINA_HOME = D:/apache-tomcat-x.x.x/bin
cd ..
set "CATALINA_HOME=%cd%"
因为 Tomcat 的目录格式是固定的, 所以这里直接进入上级目录(cd ..), 然后设置 CATALINA_HOME 的值为上级目录( D:/apache-tomcat-x.x.x ).
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
继续往下看, 这里又一次判断了一下 catalina.bat 在这样的目录结构是是否能找到, 如果我们解压完 Tomcat 后, 把 startup.bat 放在非 Tomcat 的 bin 目录下之后, 这里是找不到的, 就直接 goto end, 退出 Tomcat 的启动.
好了, 这里我们直接调到 okHome 标签处.
:okHome
set "EXECUTABLE=%CATALINA_HOME%\bin\catalina.bat"
好了, 这里很简单, 设置一个 EXECUTABLE 变量的值指向 catalina.bat 脚本.
if exist "%EXECUTABLE%" goto okExec
echo Cannot find "%EXECUTABLE%"
echo This file is needed to run this program
goto end
又一次的检查了一下这个脚本是否存在, 存在的话, 直接调到 okExec 标签处, 可以执行了.
如果没有通过检查的话, 依旧退出启动, 并打印错误信息.
:okExec
set CMD_LINE_ARGS=
:setArgs
if ""%1""=="""" goto doneSetArgs
set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
shift
goto setArgs
先设置了一个 CMD_LINE_ARGS 变量, 并且其值暂且为空
这里出现了一个 ""%1""=="""", 拆开看 就是判断 "%1" 是否等于 "". 那么 "%1" 又是什么呢?
这是 window 批处理的一个语法, 表示的是执行命令之后的第一个参数, 对于这里, 我们并没有传递什么参数, 所以这里的 "%1" 是 ""(空).
直接跳转到 doneSetArgs 标签处.
如果不是空的话, 就拼在后面呗.
这里这个 shift 命令意思就是移除一个参数, 举个例子就知道了:
@echo off
echo "%1"
shift
echo "%1"
建一个 test.bat 批处理程序, 然后把上面代码复制进去, 在 cmd 中执行并给它两个参数
下面是执行结果, 这里大家可以把 @echo off 去掉再执行, 验证一下这个命令的作用
PS D:\> .\test Hello World
"Hello"
"World"
PS D:\>
这样, 大家应该可以理解了.
继续分析
:doneSetArgs
call "%EXECUTABLE%" start %CMD_LINE_ARGS%
:end
在上面设置了 EXECUTABLE = %CATALINA_HOME%\bin\catalina.bat , 所以这里实际上是调用了 catalina.bat 这个脚本, 然后传递一个 start 参数给它.
如果我们在 cmd 中运行 startup.bat 并且后面跟着一些参数的话, 这里也一起传递过去了.
这里实际上就是执行了: %CATALINA_HOME%\bin\catalina.bat start
总结
这个脚本还是挺简单的, 目的就是找到 catalina.bat 并调用它.
[Tomcat 源码分析系列] (一) : Tomcat 启动脚本-startup.bat的更多相关文章
- [Tomcat 源码分析系列] (二) : Tomcat 启动脚本-catalina.bat
概述 Tomcat 的三个最重要的启动脚本: startup.bat catalina.bat setclasspath.bat 上一篇咱们分析了 startup.bat 脚本 这一篇咱们来分析 ca ...
- Tomcat源码分析三:Tomcat启动加载过程(一)的源码解析
Tomcat启动加载过程(一)的源码解析 今天,我将分享用源码的方式讲解Tomcat启动的加载过程,关于Tomcat的架构请参阅<Tomcat源码分析二:先看看Tomcat的整体架构>一文 ...
- Tomcat 源码分析(一)——启动与生命周期组件
写在前面的话:读Tomcat源码也有段时间了,大领悟谈不上.一些小心得记录下来,供大家参考相护学习. 一.启动流程 Tomcat启动首先需要熟悉的是它的启动流程.和初学者第一天开始写Hello Wor ...
- Tomcat源码分析(下载、启动)
1.下载Tomcat源代码: https://tomcat.apache.org/download-80.cgi 2. 解压以及创建必要目录和配置 解压.新建catalina-home目录,同时将目录 ...
- [Tomcat 源码分析系列] (附件) : catalina.bat 脚本
摘自 apache-tomcat-8.0.39-src 源码包中的 catalina.bat 脚本内容 @echo off rem Licensed to the Apache Software Fo ...
- tomcat源码分析(二)启动过程
在Catalina的load方法中,首先初始化Server组件. // Start the new server if (server instanceof Lifecycle) { try { se ...
- [Tomcat 源码分析系列] (附件) : setclasspath.bat 脚本
@echo off rem Licensed to the Apache Software Foundation (ASF) under one or more rem contributor lic ...
- tomcat源码分析(一)从tomcat架构说起
p { margin-bottom: 0.25cm; line-height: 120% }
- Tomcat源码分析之—具体启动流程分析
从Tomcat启动调用栈可知,Bootstrap类的main方法为整个Tomcat的入口,在init初始化Bootstrap类的时候为设置Catalina的工作路径也就是Catalina_HOME信息 ...
随机推荐
- DHTMLX-Windows
DHTMLX-Windows dhtmlxWindows窗口,允许用户使用几个窗户并允许windows重叠,并提供对用户执行标准操作,比如移动/调整窗口大小,发送窗口的前景/背景,最小化/最大化一个窗 ...
- Android Event
2016-10-11 http://p.codekk.com/detail/Android/wcy10586/androidEvent https://my.oschina.net/u/191330/ ...
- Linux下lampp详解 (转)
重要文件解释: ProFTPD:一个Unix平台上或是类Unix平台上(如Linux, FreeBSD等)的FTP服务器程序,它是在自由软件基金会的版权声明(GPL)下开发.发布的免费软件,可以随意修 ...
- 利用nodejs搭建服务器,测试AJAX
最近学习了AJAX一直没有进行过测试,前今天了解了Noejs搭建本地服务器下就尝试了一下.通过AJAX请求的方式获取HTTP服务器返回数据的代码 首先创建一个serve.js的文件.并写入以下代码. ...
- 函数指针_typedef
一 函数指针 1 函数类型 函数的类型由它的返回值类型,和形参类型共通过决定,与函数名无关. eg:bool lengthcompare(const string&, const string ...
- datetime
DateTime字段类型对应的时间格式是 yyyy-MM-dd HH:mm:ss.fff ,3个f,精确到1毫秒(ms),示例 2014-12-03 17:06:15.433 . DateTime2字 ...
- 添加AppWidget功能
要为程序添加AppWidget 1 首先要建立一个继承于AppWidgetProvider的类 MyWidget public class MyWidget extends AppWidgetProv ...
- 修改目的端trail文件的最大大小--转载
本文为原创,转载请注明出处: http://blog.csdn.net/msdnchina/article/details/38346435 修改目的端trail文件的最大大小. 本文产生的背景: 在 ...
- Python Quick list dir
昨天 Python释放了 3.5 ,添加了 os.scandir 根据文档该API比os.listdir快Docs which speeds it up by 3-5 times on POSIX s ...
- Ax 导出EXCEL给范围内的每个单元格加边框
1. 首先在Class\SysExcelRange加画边框的方法 思路用EXCEL录宏的功能得到给一批单元格画格子的VBA代码,在AX将对象转为COM对象,基本VBA代码也能装为AX内能用的内容. p ...