概述

我们通常使用 Tomcat 中的 startup.bat 来启动 Tomcat. 但是这其中干了一些什么事呢?

大家都知道一个 Java 程序需要启动的话, 肯定需要 main 方法, 那么这个 main 方法在哪呢?

Tomcat 脚本中又是配置了一些什么参数呢, 什么情况下 Tomcat 会启动失败呢?

带着一些列的疑问我们来分析 Tomcat 的三个最重要的启动脚本:

  • startup.bat
  • catalina.bat
  • setclasspath.bat

startup.bat 脚本

该脚本主要做了以下几件事:

  1. 设置 CATALINA_HOME 环境变量的值
  2. 找到 catalina.bat 脚本
  3. 调用 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的更多相关文章

  1. [Tomcat 源码分析系列] (二) : Tomcat 启动脚本-catalina.bat

    概述 Tomcat 的三个最重要的启动脚本: startup.bat catalina.bat setclasspath.bat 上一篇咱们分析了 startup.bat 脚本 这一篇咱们来分析 ca ...

  2. Tomcat源码分析三:Tomcat启动加载过程(一)的源码解析

    Tomcat启动加载过程(一)的源码解析 今天,我将分享用源码的方式讲解Tomcat启动的加载过程,关于Tomcat的架构请参阅<Tomcat源码分析二:先看看Tomcat的整体架构>一文 ...

  3. Tomcat 源码分析(一)——启动与生命周期组件

    写在前面的话:读Tomcat源码也有段时间了,大领悟谈不上.一些小心得记录下来,供大家参考相护学习. 一.启动流程 Tomcat启动首先需要熟悉的是它的启动流程.和初学者第一天开始写Hello Wor ...

  4. Tomcat源码分析(下载、启动)

    1.下载Tomcat源代码: https://tomcat.apache.org/download-80.cgi 2. 解压以及创建必要目录和配置 解压.新建catalina-home目录,同时将目录 ...

  5. [Tomcat 源码分析系列] (附件) : catalina.bat 脚本

    摘自 apache-tomcat-8.0.39-src 源码包中的 catalina.bat 脚本内容 @echo off rem Licensed to the Apache Software Fo ...

  6. tomcat源码分析(二)启动过程

    在Catalina的load方法中,首先初始化Server组件. // Start the new server if (server instanceof Lifecycle) { try { se ...

  7. [Tomcat 源码分析系列] (附件) : setclasspath.bat 脚本

    @echo off rem Licensed to the Apache Software Foundation (ASF) under one or more rem contributor lic ...

  8. tomcat源码分析(一)从tomcat架构说起

    p { margin-bottom: 0.25cm; line-height: 120% }

  9. Tomcat源码分析之—具体启动流程分析

    从Tomcat启动调用栈可知,Bootstrap类的main方法为整个Tomcat的入口,在init初始化Bootstrap类的时候为设置Catalina的工作路径也就是Catalina_HOME信息 ...

随机推荐

  1. Intellij IDEA +MAVEN+Jetty实现Mybatis的HelloWorld

    1 maven配置:pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="ht ...

  2. php ffmpeg

    可以合成视频,音频视频合成等 $aurl = '../Uploads/movie/zzz.mp4'; $vurl = '../Uploads/mp3/dmd.mp3'; // exec("c ...

  3. 无法打开登录所请求的数据库 "xxx"登录失败用户 'NT AUTHORITY\NETWORK SERVICE'

    解决:添加用户,选择NT AUTHORITY\SYSTEM登录名,选择当前数据库的架构. 勾选架构 勾选成员身份.如果不勾选,也会报异常:拒绝了对对象 'FW_ORG' (数据库 'ZW_DWSJ', ...

  4. makefile小例子

    makefile的知识点应该很多,看网上的很多教程就能看出来,长的可以写一本书.记录一下自己用的一个简单的makefile, 方便以后查找. 先看一下程序的目录结构: [root@localhost ...

  5. dingding post POST请求

    POST请求请在HTTP Header中设置 Content-Type:application/json,否则接口调用失败 获取AccessToken Https请求方式: GET https://o ...

  6. oracle之trunc与round

    round(x[,y]) 功能:返回四舍五入后的值 参数:x,y,数字型表达式,如果y不为整数则截取y整数部分,如果y>0则四舍五入为y位小数,如果y小于0则四舍五入到小数点向左第y位. 返回: ...

  7. ses_cations 值顺序

    16个位置的字符所代表的操作依次如下: 1. ALTER 2. AUDIT 3.COMMENT 4.DELETE 5.GRANT 6.INDEX 7.INSERT 8.LOCK 9.RENAME 10 ...

  8. Java 反射 getDeclareFields getModifiers setAccessible(true)

    示例代码: public static Map<String, Object> dtoToMap(Object obj, String pre,            String las ...

  9. 数据结构与算法(1)支线任务8——Find Median from Data Stream

    题目如下:(https://leetcode.com/problems/find-median-from-data-stream/) Median is the middle value in an ...

  10. [转载]《民航科技》2012年4月专家论坛:程延松《关于中国民航SWIM框架及技术实现探讨》

    专家介绍:程延松,现任成都民航空管发展有限公司总经理,理学博士,高级工程师,长期从事空管技术研究和产品研发工作,作为课题负责人,参与了国家863计划.国家科技支撑计划.国家空管委重点课题.民航局重点课 ...