tomcat 的启动文件 catalina.sh shell脚本详解

接上一篇文章:我们启动tomcat下的start.sh文件,shell脚本到底做了什么呢?在上一篇文章最后,start.sh 最终调用了 catalina.sh 脚本(调用命令为:exec /usr/local/apache-tomcat-9.0.21/bin/catalina.sh start "$@");那么catalina.sh 具体干了什么呢?

代码块:

# OS specific support.  $var _must_ be set to either true or false.
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

# resolve links - $0 may be a softlink
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

上述这一段代码,设定了一些变量, 并通过case判断根据服务器操作系统的不同,设置不同的参数值。通过while循环判断,获取catalina.sh的绝对路径(非链接),赋值给PRG。在服务器上执行unameLinux。比如我的tomcat的catalina.sh的绝对路径为/usr/local/apache-tomcat-9.0.21/bin/catalina.sh。此时,变量情况为:

cygwin=false
darwin=false
os400=false
hpux=false
PRG=/usr/local/apache-tomcat-9.0.21/bin/catalina.sh

代码块:

# Only set CATALINA_HOME if not already set
[ -z "$CATALINA_HOME" ] && CATALINA_HOME=`cd "$PRGDIR/.." >/dev/null; pwd`

# Copy CATALINA_BASE from CATALINA_HOME if not already set
[ -z "$CATALINA_BASE" ] && CATALINA_BASE="$CATALINA_HOME"

# Ensure that any user defined CLASSPATH variables are not used on startup,
# but allow them to be specified in setenv.sh, in rare case when it is needed.
CLASSPATH=

if [ -r "$CATALINA_BASE/bin/setenv.sh" ]; then
  . "$CATALINA_BASE/bin/setenv.sh"
elif [ -r "$CATALINA_HOME/bin/setenv.sh" ]; then
  . "$CATALINA_HOME/bin/setenv.sh"
fi

上述代码,通过-z判断变量CATALINA_HOMECATALINA_BASE是否已经设置;若未设置,则设定默认值。默认情况下,bin目录下默认是没有setenv.sh文件。所以上述代码执行后,变量变动情况如下:

PRGDIR=/usr/local/apache-tomcat-9.0.21/bin
CATALINA_HOME=/usr/local/apache-tomcat-9.0.21
CATALINA_BASE=/usr/local/apache-tomcat-9.0.21
CLASSPATH=

代码块:

# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin; then
  [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
  [ -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

# Ensure that neither CATALINA_HOME nor CATALINA_BASE contains a colon
# as this is used as the separator in the classpath and Java provides no
# mechanism for escaping if the same character appears in the path.
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

上述代码,由于$cygwin=false,跳过if判断。接下来两个case通过$CATALINA_HOME与$CATALINA_BASE的值是否包含判断服务器是否设置了环境变量。若系统设置的环境变量,会给出提示,并退出执行脚本。由于服务器没有CATALINA的环境变量设置,故此时无变量变化。
代码块:

# For OS400
if $os400; then
  # Set job priority to standard for interactive (interactive - 6) by using
  # the interactive priority - 6, the helper threads that respond to requests
  # will be running at the same priority as interactive jobs.
  COMMAND='chgjob job('$JOBNAME') runpty(6)'
  system $COMMAND

  # Enable multi threading
  export QIBM_MULTI_THREADED=Y
fi

# Get standard Java environment variables
if $os400; then
  # -r will Only work on the os400 if the files are:
  # 1. owned by the user
  # 2. owned by the PRIMARY group of the user
  # this will not work if the user belongs in secondary groups
  . "$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

由于$os400=false,所以第一段if...else...跳过,第二段if...else...进入else 。当setclasspath.sh文件可读时,执行该文件,否则给出提示,并退出脚本。
注:关于setclasspath.sh到底在干嘛,我们下次再详述。 此时变量无变化。
代码块:

# Add on extra jar files to CLASSPATH
if [ ! -z "$CLASSPATH" ] ; then
  CLASSPATH="$CLASSPATH":
fi
CLASSPATH="$CLASSPATH""$CATALINA_HOME"/bin/bootstrap.jar

if [ -z "$CATALINA_OUT" ] ; then
  CATALINA_OUT="$CATALINA_BASE"/logs/catalina.out
fi

if [ -z "$CATALINA_TMPDIR" ] ; then
  # Define the java.io.tmpdir to use for Catalina
  CATALINA_TMPDIR="$CATALINA_BASE"/temp
fi

# Add tomcat-juli.jar to classpath
# tomcat-juli.jar can be over-ridden per instance
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

上述代码,对一些变量进行简单的判断,根据情况赋值,此时变量变化情况为:

CLASSPATH= --> /usr/local/apache-tomcat-9.0.21/bin/bootstrap.jar
CATALINA_OUT=/usr/local/apache-tomcat-9.0.21/logs/catalina.out
CATALINA_TMPDIR=/usr/local/apache-tomcat-9.0.21/temp
CLASSPATH=/usr/local/apache-tomcat-9.0.21/bin/bootstrap.jar --> /usr/local/apache-tomcat-9.0.21/bin/bootstrap.jar:/usr/local/apache-tomcat-9.0.21/bin/tomcat-juli.jar

代码块:

# Bugzilla 37848: When no TTY is available, don't output to console
have_tty=0
if [ -t 1 ]; then
    have_tty=1
fi

# For Cygwin, switch paths to Windows format before running java
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"`
  [ -n "$JAVA_ENDORSED_DIRS" ] && JAVA_ENDORSED_DIRS=`cygpath --path --windows "$JAVA_ENDORSED_DIRS"`
fi

if [ -z "$JSSE_OPTS" ] ; then
  JSSE_OPTS="-Djdk.tls.ephemeralDHKeySize=2048"
fi
JAVA_OPTS="$JAVA_OPTS $JSSE_OPTS"

# Register custom URL handlers
# Do this here so custom URL handles (specifically 'war:...') can be used in the security policy
JAVA_OPTS="$JAVA_OPTS -Djava.protocol.handler.pkgs=org.apache.catalina.webresources"

# Set juli LogManager config file if it is present and an override has not been issued
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
    # Bugzilla 45585
    LOGGING_CONFIG="-Dnop"
  fi
fi

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

# Set UMASK unless it has been overridden
if [ -z "$UMASK" ]; then
    UMASK="0027"
fi
umask $UMASK

上述代码, [ -t 1 ]=true, $cygwin=false,而后是一些变量的判断。此时变量的变化为:

have_tty=1
JSSE_OPTS="-Djdk.tls.ephemeralDHKeySize=2048"
JAVA_OPTS="-Djdk.tls.ephemeralDHKeySize=2048"
JAVA_OPTS="-Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources"
LOGGING_CONFIG="-Djava.util.logging.config.file=/usr/local/apache-tomcat-9.0.21/conf/logging.properties"
LOGGING_MANAGER="-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager"
UMASK="0027"

代码块:

# Java 9 no longer supports the java.endorsed.dirs
# system property. Only try to use it if
# JAVA_ENDORSED_DIRS was explicitly set
# or CATALINA_HOME/endorsed exists.
ENDORSED_PROP=ignore.endorsed.dirs
if [ -n "$JAVA_ENDORSED_DIRS" ]; then
    ENDORSED_PROP=java.endorsed.dirs
fi
if [ -d "$CATALINA_HOME/endorsed" ]; then
    ENDORSED_PROP=java.endorsed.dirs
fi

# Make the umask available when using the org.apache.catalina.security.SecurityListener
JAVA_OPTS="$JAVA_OPTS -Dorg.apache.catalina.security.SecurityListener.UMASK=`umask`"

if [ -z "$USE_NOHUP" ]; then
    if $hpux; then
        USE_NOHUP="true"
    else
        USE_NOHUP="false"
    fi
fi
unset _NOHUP
if [ "$USE_NOHUP" = "true" ]; then
    _NOHUP="nohup"
fi

# Add the JAVA 9 specific start-up parameters required by Tomcat
JDK_JAVA_OPTIONS="$JDK_JAVA_OPTIONS --add-opens=java.base/java.lang=ALL-UNNAMED"
JDK_JAVA_OPTIONS="$JDK_JAVA_OPTIONS --add-opens=java.base/java.io=ALL-UNNAMED"
JDK_JAVA_OPTIONS="$JDK_JAVA_OPTIONS --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED"
export JDK_JAVA_OPTIONS

上述代码,[ -n "$JAVA_ENDORSED_DIRS" ]=falase, [ -d "$CATALINA_HOME/endorsed" ]=false, [ -z "$USE_NOHUP" ]=true,,此时变量变化如下:

JAVA_OPTS="-Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027"
USE_NOHUP="false"
JDK_JAVA_OPTIONS="--add-opens=java.base/java.lang=ALL-UNNAMED"
JDK_JAVA_OPTIONS="--add-opens=java.base/java.io=ALL-UNNAMED"
JDK_JAVA_OPTIONS="--add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED"

代码块:

# ----- Execute The Requested Command -----------------------------------------

# Bugzilla 37848: only output this if we have a TTY
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

上述代码没有做什么操作,只是打印了一些信息而已。
调用此脚本的外部参数为start,故下述只看 [ $1 = start ]的代码块:

if [ "$1" = "jpda" ] ; then
略
fi
if [ "$1" = "debug" ] ; then
略
elif [ "$1" = "run" ]; then
略
elif [ "$1" = "start" ] ; then

  if [ ! -z "$CATALINA_PID" ]; then
    if [ -f "$CATALINA_PID" ]; then
      if [ -s "$CATALINA_PID" ]; then
        echo "Existing PID file found during start."
        if [ -r "$CATALINA_PID" ]; then
          PID=`cat "$CATALINA_PID"`
          ps -p $PID >/dev/null 2>&1
          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
          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
      else
        rm -f "$CATALINA_PID" >/dev/null 2>&1
        if [ $? != 0 ]; then
          if [ ! -w "$CATALINA_PID" ]; then
            echo "Unable to remove or write to empty PID file. Start aborted."
            exit 1
          fi
        fi
      fi
    fi
  fi

  shift
  touch "$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 \
      -D$ENDORSED_PROP="\"$JAVA_ENDORSED_DIRS\"" \
      -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 \
      -D$ENDORSED_PROP="\"$JAVA_ENDORSED_DIRS\"" \
      -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

  if [ ! -z "$CATALINA_PID" ]; then
    echo $! > "$CATALINA_PID"
  fi

  echo "Tomcat started."
elif [ "$1" = "stop" ] ; then
略
elif [ "$1" = "configtest" ] ; then
略
elif [ "$1" = "version" ] ; then
略
else
略
fi

上述非start外部传参的判断条件省略了。[ "$1" = "start" ]=true, [ ! -z "$CATALINA_PID" ]=false,此时代码走到 shift这里,由于只有一个外部传参start,故 [ "$1" = "-security" ]=false,此时进入 else 分支,执行下述命令:

 eval $_NOHUP "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
      -D$ENDORSED_PROP="\"$JAVA_ENDORSED_DIRS\"" \
      -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 "&"

# 注:从setclasspath.sh得变量 
# _RUNJAVA=/usr/java/jdk1.8.0_91/bin/java 
# _RUNJDB=/usr/java/jdk1.8.0_91/bin/jdb 
# 上述命令,将变量替换掉,为:
 /usr/java/jdk1.8.0_91/bin/java
 -Djava.util.logging.config.file=/usr/local/apache-tomcat-9.0.21/conf/logging.properties\ 
 -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager 
 -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources    -Dorg.apache.catalina.security.SecurityListener.UMASK=0027  \
      -D$ENDORSED_PROP=\
      -classpath /usr/local/apache-tomcat-9.0.21/bin/bootstrap.jar:/usr/local/apache-tomcat-9.0.21/bin/tomcat-juli.jar\
      -Dcatalina.base=/usr/local/apache-tomcat-9.0.21 \
      -Dcatalina.home=/usr/local/apache-tomcat-9.0.21 \
      -Djava.io.tmpdir=/usr/local/apache-tomcat-9.0.21/temp \
      org.apache.catalina.startup.Bootstrap start \
      >> /usr/local/apache-tomcat-9.0.21/logs/catalina.out 2>&1 &

所以tomcat执行start.sh 脚本时,通常情况下 就是上述这么一个命令。你可以直接在命令行执行此命令:

[root@test-cdh conf]# /usr/java/jdk1.8.0_91/bin/java -Djava.util.logging.config.file=/usr/local/apache-tomcat-9.0.21/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -D= -classpath /usr/local/apache-tomcat-9.0.21/bin/bootstrap.jar:/usr/local/apache-tomcat-9.0.21/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/apache-tomcat-9.0.21 -Dcatalina.home=/usr/local/apache-tomcat-9.0.21 -Djava.io.tmpdir=/usr/local/apache-tomcat-9.0.21/temp org.apache.catalina.startup.Bootstrap start >> /usr/local/apache-tomcat-9.0.21/logs/catalina.out 2>&1 &
[1] 49852

现在是不是觉得,写的很复杂的脚本,只是一条有较多java参数的命令而已,是不是顿时豁然开朗。

附:上述有很多判断的语句,有一博文整理了,如下(链接为:https://blog.csdn.net/weixin_30367873/article/details/95135922):

运算符	描述	示例
文件比较运算符
-e filename	如果 filename 存在,则为真	[ -e /var/log/syslog ]
-d filename	如果 filename 为目录,则为真	[ -d /tmp/mydir ]
-f filename	如果 filename 为常规文件,则为真	[ -f /usr/bin/grep ]
-L filename	如果 filename 为符号链接,则为真	[ -L /usr/bin/grep ]
-r filename	如果 filename 可读,则为真	[ -r /var/log/syslog ]
-w filename	如果 filename 可写,则为真	[ -w /var/mytmp.txt ]
-x filename	如果 filename 可执行,则为真	[ -L /usr/bin/grep ]
filename1 -nt filename2	如果 filename1 比 filename2 新,则为真	[ /tmp/install/etc/services -nt /etc/services ]
filename1 -ot filename2	如果 filename1 比 filename2 旧,则为真	[ /boot/bzImage -ot arch/i386/boot/bzImage ]
字符串比较运算符 (请注意引号的使用,这是防止空格扰乱代码的好方法)
-z string	如果 string 长度为零,则为真	[ -z "$myvar" ]
-n string	如果 string 长度非零,则为真	[ -n "$myvar" ]
string1 = string2	如果 string1 与 string2 相同,则为真	[ "$myvar" = "one two three" ]
string1 != string2	如果 string1 与 string2 不同,则为真	[ "$myvar" != "one two three" ]
算术比较运算符
num1 -eq num2	等于	[ 3 -eq $mynum ]
num1 -ne num2	不等于	[ 3 -ne $mynum ]
num1 -lt num2	小于	[ 3 -lt $mynum ]
num1 -le num2	小于或等于	[ 3 -le $mynum ]
num1 -gt num2	大于	[ 3 -gt $mynum ]
num1 -ge num2	大于或等于	[ 3 -ge $mynum ]

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值