tomcat启动文件源码阅读

tomcat的启动文件主要包含三个startup.sh,setclasspath.sh,catalina.sh。

前两周作为学习bash和了解tomcat启动流程阅读了一下。

startup.sh

#!/bin/sh

# 整个启动文件的作用应该是区分os400系统来启动catalina.sh

# 判断系统是否为OS/400
#======================
os400=false
case "`uname`" in     # uname命令用来显示当前操作系统名称
OS400*) os400=true;;   # 若当前系统名称以OS400开头
esac

PRG="$0"    # $0表示文件本身名称

# 找到文件所对应的真实路径,主要是用来找到startup.sh所在的目录
#=======================================================
while [ -h "$PRG" ] ; do   # -h 表示判断文件是否存在且为软链接
  ls=`ls -ld "$PRG"`       # 显示当前文件的详细信息,对于软链接,其中文件名部分会以  xxx.xx -> /a/bb/cc 的形式显示
  link=`expr "$ls" : '.*-> \(.*\)$'`    # 取出"-> "后面的部分,即软链接实际指向的位置。expr使用冒号可以做模式匹配功能
  if expr "$link" : '/.*' > /dev/null; then   # 如果link路径为绝对路径
    PRG="$link"     
  else    # 若不是绝对路径
    PRG=`dirname "$PRG"`/"$link"
  fi
done   # 此处的循环是用来解决多个软链接的问题的,即 a -> b -> c -> d 这样的方式


# 判断catalina.sh是否可行性并执行
#=================================
PRGDIR=`dirname "$PRG"` # 获取文件的目录路径
EXECUTABLE=catalina.sh

if $os400; then
  eval
else
  if [ ! -x "$PRGDIR"/"$EXECUTABLE" ]; then # 判断文件catalina.sh是否可执行。其中"$PRGDIR"/"$EXECUTABLE"就相当于字符串拼接,不妨设$PRGDIR为/root/tomcat,那结果就是/root/tomcat/catalina.sh
    echo "Cannot find $PRGDIR/$EXECUTABLE"
    echo "The file is absent or does not have execute permission"
    echo "This file is needed to run this program"
    exit 1    # 退出并设置退出码为1
  fi
fi

exec "$PRGDIR"/"$EXECUTABLE" start "$@"  # 执行 "./cataline.sh start arg1 arg2 ..." 命令,其中start为命令的一部分

setclasspath.sh

#!/bin/sh

# 整个配置文件的作用就是用来设置java和jdb的启动命令的
# 执行流程如下:
#   1. 判断是否存在java
#   2. 若是debug模式,判断是否存在jdk
#   3. 若是debug模式,确保java, jdb和javac都能正常执行
#   4. 设置java和jdb的运行命令

# 如果JAVA_HOME和JRE_HOME都没有设置
#===================================
if [ -z "$JAVA_HOME" -a -z "$JRE_HOME" ]; then   # -a表示and
  # darwin环境下配置JAVA_HOME
  #----------------------------
  if $darwin; then
    # 设置JAVA_HOME
    if [ -x '/usr/libexec/java_home' ] ; then    # -x判断文件是否可执行
      export JAVA_HOME=`/usr/libexec/java_home`
    elif [ -d "/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home" ]; then    # -d判断文件是否是目录
      export JAVA_HOME="/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home"
    fi
  # 其他环境下配置JRE_HOME
  #------------------------
  else
    JAVA_PATH=`which java 2>/dev/null`   # which表示在PATH变量指定的路径中搜索某个系统命令所在的位置, 2>表示重定向错误信息
    if [ "x$JAVA_PATH" != "x" ]; then   # 如果JAVA_PATH为空
      # JRE_HOME 即为java的前两级目录
      JAVA_PATH=`dirname $JAVA_PATH 2>/dev/null` 
      JRE_HOME=`dirname $JAVA_PATH 2>/dev/null`
    fi
    if [ "x$JRE_HOME" = "x" ]; then   # 如果还是没有找到JRE_HOME
      if [ -x /usr/bin/java ]; then   # 判断/usr/bin下有无java
        JRE_HOME=/usr
      fi
    fi
  fi
  # JAVA_HOME 和 JRE_HOME 均未配置的情况下,退出程序
  #-----------------------------------------------
  if [ -z "$JAVA_HOME" -a -z "$JRE_HOME" ]; then
    echo "Neither the JAVA_HOME nor the JRE_HOME environment variable is defined"
    echo "At least one of these environment variable is needed to run this program"
    exit 1
  fi
fi

# 对于debug模式的情况,必须要使用jdk目录
#=====================================
if [ -z "$JAVA_HOME" -a "$1" = "debug" ]; then
  echo "JAVA_HOME should point to a JDK in order to run in debug mode."
  exit 1
fi

# 如果JRE_HOME为空,则默认使用JAVA_HOME的值
#=========================================
if [ -z "$JRE_HOME" ]; then
  JRE_HOME="$JAVA_HOME"
fi

# 如果是在debug模式下,确保java,jdb和javac都能执行
#===============================================
if [ "$1" = "debug" ] ; then
  if [ "$os400" = "true" ]; then
    if [ ! -x "$JAVA_HOME"/bin/java -o ! -x "$JAVA_HOME"/bin/javac ]; then
      echo "The JAVA_HOME environment variable is not defined correctly"
      echo "This environment variable is needed to run this program"
      echo "NB: JAVA_HOME should point to a JDK not a JRE"
      exit 1
    fi
  else
    # 确保java, jdb和javac都能执行
    #------------------------------
    if [ ! -x "$JAVA_HOME"/bin/java -o ! -x "$JAVA_HOME"/bin/jdb -o ! -x "$JAVA_HOME"/bin/javac ]; then
      echo "The JAVA_HOME environment variable is not defined correctly"
      echo "This environment variable is needed to run this program"
      echo "NB: JAVA_HOME should point to a JDK not a JRE"
      exit 1
    fi
  fi
fi

# 设置JAVA和JDB的启动命令
#=========================
if [ -z "$_RUNJAVA" ]; then
  _RUNJAVA="$JRE_HOME"/bin/java
fi
if [ "$os400" != "true" ]; then
  if [ -z "$_RUNJDB" ]; then
    _RUNJDB="$JAVA_HOME"/bin/jdb
  fi
fi

catalina.sh

#!/bin/sh

# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# -----------------------------------------------------------------------------
# Control Script for the CATALINA Server
#
# Environment Variable Prerequisites
#
#   Do not set the variables in this script. Instead put them into a script
#   setenv.sh in CATALINA_BASE/bin to keep your customizations separate.
#
#   CATALINA_HOME   May point at your Catalina "build" directory.
#
#   CATALINA_BASE   (Optional) Base directory for resolving dynamic portions
#                   of a Catalina installation.  If not present, resolves to
#                   the same directory that CATALINA_HOME points to.
#
#   CATALINA_OUT    (Optional) Full path to a file where stdout and stderr
#                   will be redirected.
#                   Default is $CATALINA_BASE/logs/catalina.out
#
#   CATALINA_OPTS   (Optional) Java runtime options used when the "start",
#                   "run" or "debug" command is executed.
#                   Include here and not in JAVA_OPTS all options, that should
#                   only be used by Tomcat itself, not by the stop process,
#                   the version command etc.
#                   Examples are heap size, GC logging, JMX ports etc.
#
#   CATALINA_TMPDIR (Optional) Directory path location of temporary directory
#                   the JVM should use (java.io.tmpdir).  Defaults to
#                   $CATALINA_BASE/temp.
#
#   JAVA_HOME       Must point at your Java Development Kit installation.
#                   Required to run the with the "debug" argument.
#
#   JRE_HOME        Must point at your Java Runtime installation.
#                   Defaults to JAVA_HOME if empty. If JRE_HOME and JAVA_HOME
#                   are both set, JRE_HOME is used.
#
#   JAVA_OPTS       (Optional) Java runtime options used when any command
#                   is executed.
#                   Include here and not in CATALINA_OPTS all options, that
#                   should be used by Tomcat and also by the stop process,
#                   the version command etc.
#                   Most options should go into CATALINA_OPTS.
#
#   JPDA_TRANSPORT  (Optional) JPDA transport used when the "jpda start"
#                   command is executed. The default is "dt_socket".
#
#   JPDA_ADDRESS    (Optional) Java runtime options used when the "jpda start"
#                   command is executed. The default is localhost:8000.
#
#   JPDA_SUSPEND    (Optional) Java runtime options used when the "jpda start"
#                   command is executed. Specifies whether JVM should suspend
#                   execution immediately after startup. Default is "n".
#
#   JPDA_OPTS       (Optional) Java runtime options used when the "jpda start"
#                   command is executed. If used, JPDA_TRANSPORT, JPDA_ADDRESS,
#                   and JPDA_SUSPEND are ignored. Thus, all required jpda
#                   options MUST be specified. The default is:
#
#                   -agentlib:jdwp=transport=$JPDA_TRANSPORT,
#                       address=$JPDA_ADDRESS,server=y,suspend=$JPDA_SUSPEND
#
#   JSSE_OPTS       (Optional) Java runtime options used to control the TLS
#                   implementation when JSSE is used. Default is:
#                   "-Djdk.tls.ephemeralDHKeySize=2048"
#
#   CATALINA_PID    (Optional) Path of the file which should contains the pid
#                   of the catalina startup java process, when start (fork) is
#                   used
#
#   LOGGING_CONFIG  (Optional) Override Tomcat's logging config file
#                   Example (all one line)
#                   LOGGING_CONFIG="-Djava.util.logging.config.file=$CATALINA_BASE/conf/logging.properties"
#
#   LOGGING_MANAGER (Optional) Override Tomcat's logging manager
#                   Example (all one line)
#                   LOGGING_MANAGER="-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager"
#
#   UMASK           (Optional) Override Tomcat's default UMASK of 0027
#
#   USE_NOHUP       (Optional) If set to the string true the start command will
#                   use nohup so that the Tomcat process will ignore any hangup
#                   signals. Default is "false" unless running on HP-UX in which
#                   case the default is "true"
# -----------------------------------------------------------------------------

# 判断当前操作系统
#===================
cygwin=false
darwin=false
os400=false
hpux=false
case "`uname`" in
CYGWIN*) cygwin=true;;
Darwin*) darwin=true;;
OS400*) os400=true;;
HP-UX*) hpux=true;;
esac

PRG="$0"

# 若当前文件为软链接,则找到其指向的真实文件
#=======================================
while [ -h "$PRG" ]; do
  ls=`ls -ld "$PRG"`
  link=`expr "$ls" : '.*-> \(.*\)$'`
  if expr "$link" : '/.*' > /dev/null; then
    PRG="$link"
  else
    PRG=`dirname "$PRG"`/"$link"
  fi
done

PRGDIR=`dirname "$PRG"`

[ -z "$CATALINA_HOME" ] && CATALINA_HOME=`cd "$PRGDIR/.." >/dev/null; pwd` # -z 判断字符串长度是否为0。若CATALINA_HOME还不存在,则设置CATALINA_HOME环境变量为apache目录

[ -z "$CATALINA_BASE" ] && CATALINA_BASE="$CATALINA_HOME"  # 若CATALINA_BASE还不存在,则设置CATALINA_BASE环境变量为apache目录

# 将CLASSPATH设置为空。确保用户自己定义的CLASSPATH不会被使用,对于使用setenv.sh的特殊情况则执行setenv.sh
#=================================================================================================
CLASSPATH=      # 设置CLASSPATH为空

# 对于使用setenv.sh的特殊情况,进行执行
if [ -r "$CATALINA_BASE/bin/setenv.sh" ]; then   # -r判断文件是否存在且可读
  . "$CATALINA_BASE/bin/setenv.sh"
elif [ -r "$CATALINA_HOME/bin/setenv.sh" ]; then
  . "$CATALINA_HOME/bin/setenv.sh"
fi

# 对于Cygwin系统,将几个环境变量路径全部转换为unix格式
#===================================================
if $cygwin; then
  [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`   # -n 表示判断字符串长度是否不为0。cygpath --unix表示将路径转换为unix格式
  [ -n "$JRE_HOME" ] && JRE_HOME=`cygpath --unix "$JRE_HOME"`
  [ -n "$CATALINA_HOME" ] && CATALINA_HOME=`cygpath --unix "$CATALINA_HOME"`
  [ -n "$CATALINA_BASE" ] && CATALINA_BASE=`cygpath --unix "$CATALINA_BASE"`
  [ -n "$CLASSPATH" ] && CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi

# 确保CATALINA_HOME和CATALINA_BASE中均不包含冒号
#================================================
case $CATALINA_HOME in
  *:*) echo "Using CATALINA_HOME:   $CATALINA_HOME";
       echo "Unable to start as CATALINA_HOME contains a colon (:) character";
       exit 1;
esac
case $CATALINA_BASE in
  *:*) echo "Using CATALINA_BASE:   $CATALINA_BASE";
       echo "Unable to start as CATALINA_BASE contains a colon (:) character";
       exit 1;
esac

if $os400; then
  COMMAND='chgjob job('$JOBNAME') runpty(6)'
  system $COMMAND

  export QIBM_MULTI_THREADED=Y
fi


# 执行setclasspath.sh
#=========================
if $os400; then
  . "$CATALINA_HOME"/bin/setclasspath.sh
else
  if [ -r "$CATALINA_HOME"/bin/setclasspath.sh ]; then
    . "$CATALINA_HOME"/bin/setclasspath.sh
  else
    echo "Cannot find $CATALINA_HOME/bin/setclasspath.sh"
    echo "This file is needed to run this program"
    exit 1
  fi
fi

# 向CLASSPATH中添加bootstrap.jar包
#==================================
if [ ! -z "$CLASSPATH" ] ; then
  CLASSPATH="$CLASSPATH":         # 在CLASSPATH后面添加一个冒号
fi
CLASSPATH="$CLASSPATH""$CATALINA_HOME"/bin/bootstrap.jar     # 向CLASSPATH中添加bootstrap.jar包

# 设置CATALINA_OUT变量
#=======================
if [ -z "$CATALINA_OUT" ] ; then
  CATALINA_OUT="$CATALINA_BASE"/logs/catalina.out
fi

# 设置CATALINA_TMPDIR变量
#==========================
if [ -z "$CATALINA_TMPDIR" ] ; then
  CATALINA_TMPDIR="$CATALINA_BASE"/temp
fi

# 将tomcat-juli.jar包添加进CLASSPATH中
#======================================
if [ -r "$CATALINA_BASE/bin/tomcat-juli.jar" ] ; then
  CLASSPATH=$CLASSPATH:$CATALINA_BASE/bin/tomcat-juli.jar
else
  CLASSPATH=$CLASSPATH:$CATALINA_HOME/bin/tomcat-juli.jar
fi

# 判断是否存在终端
#==================
have_tty=0
if [ "`tty`" != "not a tty" ]; then
    have_tty=1
fi

# 对于Cygwin系统,将路径全部转换为windows格式
#===========================================
if $cygwin; then
  JAVA_HOME=`cygpath --absolute --windows "$JAVA_HOME"`
  JRE_HOME=`cygpath --absolute --windows "$JRE_HOME"`
  CATALINA_HOME=`cygpath --absolute --windows "$CATALINA_HOME"`
  CATALINA_BASE=`cygpath --absolute --windows "$CATALINA_BASE"`
  CATALINA_TMPDIR=`cygpath --absolute --windows "$CATALINA_TMPDIR"`
  CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
fi

# 配置JSSE_OPTS
#=================
if [ -z "$JSSE_OPTS" ] ; then     # 若没有配置JSSE_OPTS则设置默认JSSE_OPTS
  JSSE_OPTS="-Djdk.tls.ephemeralDHKeySize=2048"
fi
JAVA_OPTS="$JAVA_OPTS $JSSE_OPTS"    # 向Java启动选项中添加JSSE_OPTS配置

JAVA_OPTS="$JAVA_OPTS -Djava.protocol.handler.pkgs=org.apache.catalina.webresources"

# 配置日志文件及管理器
#======================
if [ -z "$LOGGING_CONFIG" ]; then
  if [ -r "$CATALINA_BASE"/conf/logging.properties ]; then
    LOGGING_CONFIG="-Djava.util.logging.config.file=$CATALINA_BASE/conf/logging.properties"
  else
    LOGGING_CONFIG="-Dnop"
  fi
fi

if [ -z "$LOGGING_MANAGER" ]; then
  LOGGING_MANAGER="-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager"
fi

# 若之前没有配置默认权限,则设置文件默认权限为640,目录默认权限为750
#===============================================================
if [ -z "$UMASK" ]; then
    UMASK="0027"
fi
umask $UMASK

# 设置是否使用nohup方式
#=======================
if [ -z "$USE_NOHUP" ]; then
    if $hpux; then
        USE_NOHUP="true"
    else
        USE_NOHUP="false"
    fi
fi
unset _NOHUP        # unset删除变量
if [ "$USE_NOHUP" = "true" ]; then
    _NOHUP=nohup
fi


# 如果有终端,就输出如下提示信息
#==============================
if [ $have_tty -eq 1 ]; then
  echo "Using CATALINA_BASE:   $CATALINA_BASE"
  echo "Using CATALINA_HOME:   $CATALINA_HOME"
  echo "Using CATALINA_TMPDIR: $CATALINA_TMPDIR"
  if [ "$1" = "debug" ] ; then
    echo "Using JAVA_HOME:       $JAVA_HOME"
  else
    echo "Using JRE_HOME:        $JRE_HOME"
  fi
  echo "Using CLASSPATH:       $CLASSPATH"
  if [ ! -z "$CATALINA_PID" ]; then
    echo "Using CATALINA_PID:    $CATALINA_PID"
  fi
fi

# 如果启动选项的第一个参数为jpda,则进行jpda相应设置,可以自己设置运行参数,也可以使用默认参数
# 使用jpda调试catalina
# jpda的方式与start联用,虽然看下文代码部分,好像也可以同时使用jpda debug、jpda run等其他组合,但不知运行结果是否正常
#=========================================================================================================
if [ "$1" = "jpda" ] ; then
  if [ -z "$JPDA_TRANSPORT" ]; then
    JPDA_TRANSPORT="dt_socket"
  fi
  if [ -z "$JPDA_ADDRESS" ]; then
    JPDA_ADDRESS="localhost:8000"
  fi
  if [ -z "$JPDA_SUSPEND" ]; then
    JPDA_SUSPEND="n"
  fi
  if [ -z "$JPDA_OPTS" ]; then
    JPDA_OPTS="-agentlib:jdwp=transport=$JPDA_TRANSPORT,address=$JPDA_ADDRESS,server=y,suspend=$JPDA_SUSPEND"
  fi
  CATALINA_OPTS="$JPDA_OPTS $CATALINA_OPTS"
  shift
fi


# 如果启动选项的第一个参数为debug
# 在调试器中启动catalina
#=================================
if [ "$1" = "debug" ] ; then
  if $os400; then
    echo "Debug command not available on OS400"
    exit 1
  else
    shift    # 位置参数左移。即原来的$2变为$1,原来的$3变为$2
    if [ "$1" = "-security" ] ; then   # 使用带有安全管理器的调试
      if [ $have_tty -eq 1 ]; then
        echo "Using Security Manager"
      fi
      shift
      exec "$_RUNJDB" "$LOGGING_CONFIG" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
        -classpath "$CLASSPATH" \
        -sourcepath "$CATALINA_HOME"/../../java \
        -Djava.security.manager \
        -Djava.security.policy=="$CATALINA_BASE"/conf/catalina.policy \
        -Dcatalina.base="$CATALINA_BASE" \
        -Dcatalina.home="$CATALINA_HOME" \
        -Djava.io.tmpdir="$CATALINA_TMPDIR" \
        org.apache.catalina.startup.Bootstrap "$@" start
    else
      exec "$_RUNJDB" "$LOGGING_CONFIG" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
        -classpath "$CLASSPATH" \
        -sourcepath "$CATALINA_HOME"/../../java \
        -Dcatalina.base="$CATALINA_BASE" \
        -Dcatalina.home="$CATALINA_HOME" \
        -Djava.io.tmpdir="$CATALINA_TMPDIR" \
        org.apache.catalina.startup.Bootstrap "$@" start
    fi
  fi

# 如果启动选项的第一个参数为run
# 在当前窗口启动catalina
#=============================
elif [ "$1" = "run" ]; then

  shift
  if [ "$1" = "-security" ] ; then
    if [ $have_tty -eq 1 ]; then
      echo "Using Security Manager"
    fi
    shift
    eval exec "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
      -classpath "\"$CLASSPATH\"" \
      -Djava.security.manager \
      -Djava.security.policy=="\"$CATALINA_BASE/conf/catalina.policy\"" \
      -Dcatalina.base="\"$CATALINA_BASE\"" \
      -Dcatalina.home="\"$CATALINA_HOME\"" \
      -Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
      org.apache.catalina.startup.Bootstrap "$@" start
  else
    eval exec "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
      -classpath "\"$CLASSPATH\"" \
      -Dcatalina.base="\"$CATALINA_BASE\"" \
      -Dcatalina.home="\"$CATALINA_HOME\"" \
      -Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
      org.apache.catalina.startup.Bootstrap "$@" start
  fi

# 如果启动选项的第一个参数为start
# 在新的窗口启动Catalina
#================================
elif [ "$1" = "start" ] ; then

  # 从下文中我们可以知道,其实CATALINA_PID文件中保存的就是CATALINA执行后的进程PID
  #-----------------------------------------------------------------------
  if [ ! -z "$CATALINA_PID" ]; then  # 如果设置了CATALINA_PID
    if [ -f "$CATALINA_PID" ]; then   # 如果已经存在CATALINA_PID文件了
      # 如果CATALINA_PID文件中已经有内容了,则判断是否已经有相应进程正在运行,若没有运行的进程,则尝试删除或清空CATALINA_PID文件
      #----------------------------------------------------------------------------------------------------------
      if [ -s "$CATALINA_PID" ]; then   # 如果CATALINA_PID文件中已经有内容了
        echo "Existing PID file found during start."
        if [ -r "$CATALINA_PID" ]; then
          PID=`cat "$CATALINA_PID"`
          ps -p $PID >/dev/null 2>&1
          # 如果已经有CATALINA在执行,则启动失败
          if [ $? -eq 0 ] ; then 
            echo "Tomcat appears to still be running with PID $PID. Start aborted."
            echo "If the following process is not a Tomcat process, remove the PID file and try again:"
            ps -f -p $PID
            exit 1
          # 如果没有CATALINA在执行,那么就尝试删除CATALINA_PID文件或者清空
          else
            echo "Removing/clearing stale PID file."
            rm -f "$CATALINA_PID" >/dev/null 2>&1
            if [ $? != 0 ]; then
              if [ -w "$CATALINA_PID" ]; then
                cat /dev/null > "$CATALINA_PID"
              else
                echo "Unable to remove or clear stale PID file. Start aborted."
                exit 1
              fi
            fi
          fi
        else
          echo "Unable to read PID file. Start aborted."
          exit 1
        fi
      # 如果CATALINA_PID文件为空文件,就尝试删除该文件,若无法删除,则直接尝试向该文件中写入数据
      #------------------------------------------------------------------------------
      else
        rm -f "$CATALINA_PID" >/dev/null 2>&1   # 2>&1表示将stderr重定向到stdout
        if [ $? != 0 ]; then   # 已存在的CATALINA_PID不可删除
          if [ ! -w "$CATALINA_PID" ]; then   # CATALINA_PID不可写
            echo "Unable to remove or write to empty PID file. Start aborted."
            exit 1
          fi
        fi
      fi
    fi
  fi

  shift
  touch "$CATALINA_OUT"   # 创建CATALINA_OUT的输出文件
  if [ "$1" = "-security" ] ; then
    if [ $have_tty -eq 1 ]; then
      echo "Using Security Manager"
    fi
    shift
    eval $_NOHUP "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
      -classpath "\"$CLASSPATH\"" \
      -Djava.security.manager \
      -Djava.security.policy=="\"$CATALINA_BASE/conf/catalina.policy\"" \
      -Dcatalina.base="\"$CATALINA_BASE\"" \
      -Dcatalina.home="\"$CATALINA_HOME\"" \
      -Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
      org.apache.catalina.startup.Bootstrap "$@" start \
      >> "$CATALINA_OUT" 2>&1 "&"

  else
    eval $_NOHUP "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
      -classpath "\"$CLASSPATH\"" \
      -Dcatalina.base="\"$CATALINA_BASE\"" \
      -Dcatalina.home="\"$CATALINA_HOME\"" \
      -Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
      org.apache.catalina.startup.Bootstrap "$@" start \
      >> "$CATALINA_OUT" 2>&1 "&"

  fi

  # 将执行的后台进程的PID写进CATALINA_PID文件中
  #------------------------------------------
  if [ ! -z "$CATALINA_PID" ]; then
    echo $! > "$CATALINA_PID"  
  fi

  echo "Tomcat started."


# 如果启动选项的第一个参数为stop
# 关闭catalina
#===============================
elif [ "$1" = "stop" ] ; then

  shift

  # 设置休眠时间。若stop后面的一个参数为数字,则设置为休眠时间,否则使用默认的5
  SLEEP=5
  if [ ! -z "$1" ]; then
    echo $1 | grep "[^0-9]" >/dev/null 2>&1   # 判断stop后第一个参数中是否存在非数字
    if [ $? -gt 0 ]; then   # 若只有数字,则将SLEEP设置为该时间
      SLEEP=$1
      shift
    fi
  fi

  # 设置force
  FORCE=0
  if [ "$1" = "-force" ]; then
    shift
    FORCE=1
  fi

  if [ ! -z "$CATALINA_PID" ]; then
    if [ -f "$CATALINA_PID" ]; then
      if [ -s "$CATALINA_PID" ]; then
        kill -0 `cat "$CATALINA_PID"` >/dev/null 2>&1  # kill -0 表示判断一个进程是否存在
        if [ $? -gt 0 ]; then  # 返回值大于0,即不存在
          echo "PID file found but no matching process was found. Stop aborted."
          exit 1
        fi
      else
        echo "PID file is empty and has been ignored."
      fi
    else
      echo "\$CATALINA_PID was set but the specified file does not exist. Is Tomcat running? Stop aborted."
      exit 1
    fi
  fi

  # 通过程序本身进行停止操作
  eval "\"$_RUNJAVA\"" $JAVA_OPTS \
    -classpath "\"$CLASSPATH\"" \
    -Dcatalina.base="\"$CATALINA_BASE\"" \
    -Dcatalina.home="\"$CATALINA_HOME\"" \
    -Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
    org.apache.catalina.startup.Bootstrap "$@" stop

  # 若停止失败,则调用kill命令来杀死进程
  if [ $? != 0 ]; then
    if [ ! -z "$CATALINA_PID" ]; then
      echo "The stop command failed. Attempting to signal the process to stop through OS signal."
      kill -15 `cat "$CATALINA_PID"` >/dev/null 2>&1     # 使用-15方式结束进程
    fi
  fi

  if [ ! -z "$CATALINA_PID" ]; then
    if [ -f "$CATALINA_PID" ]; then
      while [ $SLEEP -ge 0 ]; do
        kill -0 `cat "$CATALINA_PID"` >/dev/null 2>&1   # 判断进程是否存在
        if [ $? -gt 0 ]; then    # 若进行已经不存在了,就删除或清空CATALINA_PID文件
          rm -f "$CATALINA_PID" >/dev/null 2>&1
          if [ $? != 0 ]; then
            if [ -w "$CATALINA_PID" ]; then
              cat /dev/null > "$CATALINA_PID"
              FORCE=0     # 已经停止的情况下,将FORCE标记置为0
            else
              echo "The PID file could not be removed or cleared."
            fi
          fi
          echo "Tomcat stopped."
          break
        fi
        if [ $SLEEP -gt 0 ]; then  # 休眠一秒
          sleep 1
        fi
        if [ $SLEEP -eq 0 ]; then   # 休眠时间到了
          echo "Tomcat did not stop in time."
          if [ $FORCE -eq 0 ]; then
            echo "PID file was not removed."
          fi
          echo "To aid diagnostics a thread dump has been written to standard out."
          kill -3 `cat "$CATALINA_PID"`    # 使用-3方式结束进程
        fi
        SLEEP=`expr $SLEEP - 1 `
      done
    fi
  fi

  # 如果需要强制结束进程,-force命令需要CATALINA_PID存在
  KILL_SLEEP_INTERVAL=5
  if [ $FORCE -eq 1 ]; then
    if [ -z "$CATALINA_PID" ]; then
      echo "Kill failed: \$CATALINA_PID not set"
    else
      if [ -f "$CATALINA_PID" ]; then
        PID=`cat "$CATALINA_PID"`
        echo "Killing Tomcat with the PID: $PID"
        kill -9 $PID    # 使用-9方式结束进程
        # 等待5秒钟
        while [ $KILL_SLEEP_INTERVAL -ge 0 ]; do
            kill -0 `cat "$CATALINA_PID"` >/dev/null 2>&1
            if [ $? -gt 0 ]; then
                rm -f "$CATALINA_PID" >/dev/null 2>&1
                if [ $? != 0 ]; then
                    if [ -w "$CATALINA_PID" ]; then
                        cat /dev/null > "$CATALINA_PID"
                    else
                        echo "The PID file could not be removed."
                    fi
                fi
                echo "The Tomcat process has been killed."
                break
            fi
            if [ $KILL_SLEEP_INTERVAL -gt 0 ]; then
                sleep 1
            fi
            KILL_SLEEP_INTERVAL=`expr $KILL_SLEEP_INTERVAL - 1 `
        done
        # 进程关闭失败
        if [ $KILL_SLEEP_INTERVAL -lt 0 ]; then
            echo "Tomcat has not been killed completely yet. The process might be waiting on some system call or might be UNINTERRUPTIBLE."
        fi
      fi
    fi
  fi

# 如果启动选项的第一个参数为configtest
# 使用语法分析器检查server.xml
elif [ "$1" = "configtest" ] ; then

    eval "\"$_RUNJAVA\"" $LOGGING_MANAGER $JAVA_OPTS \
      -classpath "\"$CLASSPATH\"" \
      -Dcatalina.base="\"$CATALINA_BASE\"" \
      -Dcatalina.home="\"$CATALINA_HOME\"" \
      -Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
      org.apache.catalina.startup.Bootstrap configtest
    result=$?
    if [ $result -ne 0 ]; then
        echo "Configuration error detected!"
    fi
    exit $result

# 如果启动选项的第一个参数为version
# 显示tomcat的版本信息
elif [ "$1" = "version" ] ; then

    "$_RUNJAVA"   \
      -classpath "$CATALINA_HOME/lib/catalina.jar" \
      org.apache.catalina.util.ServerInfo

# 否则,输出tomcat的启动方法
else

  echo "Usage: catalina.sh ( commands ... )"
  echo "commands:"
  if $os400; then
    echo "  debug             Start Catalina in a debugger (not available on OS400)"
    echo "  debug -security   Debug Catalina with a security manager (not available on OS400)"
  else
    echo "  debug             Start Catalina in a debugger"
    echo "  debug -security   Debug Catalina with a security manager"
  fi
  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, waiting up to 5 seconds for the process to end"
  echo "  stop n            Stop Catalina, waiting up to n seconds for the process to end"
  echo "  stop -force       Stop Catalina, wait up to 5 seconds and then use kill -KILL if still running"
  echo "  stop n -force     Stop Catalina, wait up to n seconds and then use kill -KILL if still running"
  echo "  configtest        Run a basic syntax check on server.xml - check exit code for result"
  echo "  version           What version of tomcat are you running?"
  echo "Note: Waiting for the process to end and use of the -force option require that \$CATALINA_PID is defined"
  exit 1

fi

你可能感兴趣的:(tomcat启动文件源码阅读)