[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信息 ...
随机推荐
- GitBook制作电子书详细教程(命令行版)
GitBook 是一款基于 Node.js 开发的开源的工具,可以通过命令行的方式创建电子书项目,再使用 MarkDown 编写电子书内容,然后生成 PDF.ePub.mobi 格式的电子书,或生成一 ...
- js封装、简单实例源码记录
1.运动封装:doMove ( obj, attr, dir, target, endFn ) 加入回调.&&.||用法注释 <script> var oBtn1 = d ...
- Oracle 支持在具有 DHCP 分配的 IP 地址的系统上进行安装
今天在安装Oracle 10g的时候,遇到了“ Oracle 支持在具有 DHCP 分配的 IP 地址的系统上进行安装” 这个问题,经过搜索,找到了解决方案,具体如下: win7下右键单机" ...
- MVC4 +EasyUI 使用TreeGrid 方法
用easyui已经有2年了,换了新环境,要求用mvc开发,所以想把原来的项目直接用mvc重构. 在使用TreeGird的时候出现了问题,发现在转换为treegrid的json 很费劲,一直都是用的ea ...
- shape--用代码修改shape的颜色属性
Android里面经常会使用shape来定制一些View的背景,可以修改View的背景颜色,形状等属性 一般情况下,shape都是在xml文件里面写死了,今天遇到一个需求,View的形状是圆角的,但是 ...
- Talk about VR
Virtual reality --VR ,虚拟现实,是利用计算机模拟一个三维空间的世界,提供用户关于各种感官的模拟,让用户感觉身临其境,可以及时,没有限制地观察三维空间内的事物,用户进行位置移动时, ...
- 强大的commons
在此之前对commons包了解的不多,最常用的就是StringUtils.isBlack(str)来取代if(str !=null && str.lenght()>1)的判断,昨 ...
- sqlserver ,left join 不仅可以join表,还可以是一个结果集
SELECT MA.NAME AS MakeName , M.ID AS ModelId , M.Name AS ModelName , M.Warranty AS ModelWarranty , S ...
- how to enable remote access for root user
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION;
- 《JavaScript高级程序设计》学习笔记(2)--JS运算符详解
欢迎关注本人的微信公众号"前端小填填",专注前端技术的基础和项目开发的学习. 思维导图 前面对JS的运算符的操作很多细节的东西没有提及,今天给大家分享一张网上找的思维导图,对这一部 ...