深入分析:为什么 catalina.sh stop 10 无效?揭示 Tomcat 脚本中的问题

深入分析:为什么 catalina.sh stop 10 无效?揭示 Tomcat 脚本中的问题

前言

在接触 Tomcat 过程中,发现 catalina.sh --help 中明明写着可以延迟关闭,但我加了10秒也没有生效,如果只是用catalina.sh stop 官方说明也会延迟五秒关闭,但事实就是无论这两种哪个,都不会延迟关闭,要算的话大概只有1秒。

系统版本

# 操作系统:CentOS 7
# Tomcat :9.0.96
# JDK :8

# Tomcat 版本
[root@centos7 tomcat]#catalina.sh version
Using CATALINA_BASE:   /usr/local/tomcat
Using CATALINA_HOME:   /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME:        /usr/java/default/jre
Using CLASSPATH:       /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Using CATALINA_OPTS:
Using CATALINA_PID:    /usr/local/tomcat/temp/tomcat.pid
Server version: Apache Tomcat/9.0.96
Server built:   Oct 3 2024 19:44:30 UTC
Server number:  9.0.96.0
OS Name:        Linux
OS Version:     3.10.0-1160.102.1.el7.x86_64
Architecture:   amd64
JVM Version:    1.8.0_431-b10
JVM Vendor:     Oracle Corporation
[root@centos7 tomcat]#

# jdk 版本
[root@centos7 tomcat]#java -version
java version "1.8.0_431"
Java(TM) SE Runtime Environment (build 1.8.0_431-b10)
Java HotSpot(TM) 64-Bit Server VM (build 25.431-b10, mixed mode)
[root@centos7 tomcat]#

二进制安装 Tomcat

# 官网和镜像网站下载:
[root@centos7 ~]#wget https://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-9/v9.0.96/bin/apache-tomcat-9.0.96.tar.gz
[root@centos7 ~]#tar xf apache-tomcat-9.0.96.tar.gz -C /usr/local/
[root@centos7 ~]#cd /usr/local/
[root@centos7 local]#ln -s apache-tomcat-9.0.96/ tomcat
[root@centos7 local]#ls tomcat -dl
lrwxrwxrwx 1 root root 21 Oct 18 13:49 tomcat -> apache-tomcat-9.0.96/
[root@centos7 local]#

# 指定 PATH 变量
[root@centos7 local]#echo 'PATH=$PATH:/usr/local/tomcat/bin' > /etc/profile.d/tomcat.sh
[root@centos7 local]#source /etc/profile.d/tomcat.sh
[root@centos7 local]#echo $PATH
/usr/java/default/bin:/apps/httpd/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/tomcat/bin

# 查看当前变量设置和命令用法
[root@centos7 local]#catalina.sh
Using CATALINA_BASE:   /usr/local/tomcat
Using CATALINA_HOME:   /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME:        /usr/java/default
Using CLASSPATH:       /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Using CATALINA_OPTS:
Usage: catalina.sh ( commands ... )
commands:
  debug             Start Catalina in a debugger #运行 Tomcat 并附加调试器(用于开发时调试 Tomcat)。
  debug -security   Debug Catalina with a security manager #在启用了安全管理器的情况下以调试模式启动 Tomcat。
  jpda start        Start Catalina under JPDA debugger #使用 Java Platform Debugger Architecture (JPDA) 调试器启动 Tomcat(常用于远程调试)。
  run               Start Catalina in the current window #直接在当前终端窗口中启动 Tomcat(没有后台运行,会一直占用该窗口)。
  run -security     Start in the current window with security manager #在当前终端窗口中并启用安全管理器的情况下启动 Tomcat。
  start             Start Catalina in a separate window #启动 Tomcat 并让其在后台运行(常用的启动方式,不会占用当前终端)。
  start -security   Start in a separate window with security manager #在后台启动 Tomcat,并启用安全管理器。
  stop              Stop Catalina, waiting up to 5 seconds for the process to end #停止 Tomcat,默认等待 5 秒钟让进程正常退出。
  stop n            Stop Catalina, waiting up to n seconds for the process to end #停止 Tomcat,等待 n 秒钟以允许进程正常退出。
  stop -force       Stop Catalina, wait up to 5 seconds and then use kill -KILL if still running #停止 Tomcat,等待最多 5 秒后,如果进程仍未退出,则强制使用 kill -KILL 杀掉进程。
  stop n -force     Stop Catalina, wait up to n seconds and then use kill -KILL if still running #停止 Tomcat,等待 n 秒钟后,如果进程仍未退出,则使用 kill -KILL 强制杀掉进程。
  configtest        Run a basic syntax check on server.xml - check exit code for result #运行基本的 server.xml 配置文件语法检查(可以用于检查配置是否正确)。
  version           What version of tomcat are you running? #显示当前 Tomcat 的版本信息。
Note: Waiting for the process to end and use of the -force option require that $CATALINA_PID is defined #使用 `stop` 命令时,如果需要强制停止,必须确保已经定义了 `CATALINA_PID` 变量,它表示 Tomcat 运行时存储其进程 ID 的文件路径。

配置 CATALINA_PID 变量

CATALINA_PID 是一个环境变量,用于指定 Tomcat 运行时保存其进程 ID(PID)的文件路径。这个 PID 文件的作用是记录 Tomcat 进程的 PID,方便在启动、停止或重启时进行进程管理。

可选项:默认情况下,Tomcat 不需要 CATALINA_PID 变量即可正常启动和停止。

推荐定义:如果您希望更方便地管理 Tomcat 进程,特别是在编写启动和停止脚本时,建议定义 CATALINA_PID。如果是使用 service 文件来管理,那这个就不需要定义。

如果要使用 catalina.sh stop 必须先配置 CATALINA_PID,因为脚本中是通过 CATALINA_PID来记录 Tomcat 的运行的pid,然后通过读取这个文件拿到进程编号,来kii掉。

# 配置 CATALINA_PID 变量,可以在环境变量配置文件或启动脚本中定义 CATALINA_PID
[root@centos7 temp]#vim /usr/local/tomcat/bin/catalina.sh
export CATALINA_PID=/usr/local/tomcat/temp/tomcat.pid

# 或者在环境变量配置文件中定义
[root@centos7 temp]#vim /etc/profile.d/tomcat.sh
export CATALINA_PID=/usr/local/tomcat/temp/tomcat.pid

# 启动 Tomcat 多了一行信息:Using CATALINA_PID:    /usr/local/tomcat/temp/tomcat.pid
[root@centos7 temp]#startup.sh
Using CATALINA_BASE:   /usr/local/tomcat
Using CATALINA_HOME:   /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME:        /usr/java/default
Using CLASSPATH:       /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Using CATALINA_OPTS:
Using CATALINA_PID:    /usr/local/tomcat/temp/tomcat.pid #多出的信息
Tomcat started.

# 测试两次延迟关闭 Tomcat,但总是立马就退出了
[root@centos7 tomcat]#catalina.sh stop
Using CATALINA_BASE:   /usr/local/tomcat
Using CATALINA_HOME:   /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME:        /usr/java/default/jre
Using CLASSPATH:       /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Using CATALINA_OPTS:
Using CATALINA_PID:    /usr/local/tomcat/temp/tomcat.pid
Tomcat stopped.
[root@centos7 tomcat]#catalina.sh stop 10

修改官方自带的 catalina.sh 脚本

通读了一遍catalina.sh脚本,发现原来是官方自带的脚本中有点小问题,所以导致 catalina.sh stop n 这个命令无效。

elif [ "$1" = "stop" ] ; then

  shift

  SLEEP=5
  if [ ! -z "$1" ]; then
    echo $1 | grep "[^0-9]" >/dev/null 2>&1
    if [ $? -gt 0 ]; then
      SLEEP=$1
      shift
    fi
  fi

  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
        if [ $? -gt 0 ]; then
          echo "PID file found but either no matching process was found or the current user does not have permission to stop the process. 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\"" $LOGGING_MANAGER "$JAVA_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 "$@" stop

  # stop failed. Shutdown port disabled? Try a normal 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
    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
          rm -f "$CATALINA_PID" >/dev/null 2>&1
          if [ $? != 0 ]; then
            if [ -w "$CATALINA_PID" ]; then
              cat /dev/null > "$CATALINA_PID"
              # If Tomcat has stopped don't try and force a stop with an empty PID file
              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	# 官方脚本中这里默认写的就是1,无论前面的变量到底赋值是多少,这里都定义的是1。
        fi
# 在文件第592行
vim +592 catalina.sh

sleep 1
# 修改成
sleep $SLEEP

配合 CATALINA_PID 之Tomcat的启停脚本

#! /bin/bash
#-----------------------------------------------------
#Author:            XingYuyu
#Date:              2024-10-18
#Blog:              http://8.141.4.74
#Filename:          start_tomcat.sh
#Description:       [Enter Description Here]
#-----------------------------------------------------

# 定义变量
TOMCAT_HOME=/usr/local/tomcat
PID_FILE=${TOMCAT_HOME}/temp/tomcat.pid

start() {
    if [ -f "$PID_FILE" ] && [ -s "$PID_FILE" ]; then
        PID=$(cat "$PID_FILE")
        if ps -p $PID > /dev/null 2>&1; then
            echo "Tomcat 已经在运行,进程号:$PID"
            exit 1
        else
            echo "发现过期的 PID 文件,删除..."
            rm -f "$PID_FILE"
        fi
    fi
    echo "启动 Tomcat..."
    $TOMCAT_HOME/bin/startup.sh
}

stop() {
    if [ -f "$PID_FILE" ] && [ -s "$PID_FILE" ]; then
        PID=$(cat "$PID_FILE")
        if ps -p $PID > /dev/null 2>&1; then
            echo "停止 Tomcat,进程号:$PID"
            kill $PID
            sleep 5
            if ps -p $PID > /dev/null 2>&1; then
                echo "进程未停止,强制杀死..."
                kill -9 $PID
            fi
            rm -f "$PID_FILE"
        else
            echo "PID 文件存在,但进程 $PID 不存在,删除 PID 文件..."
            rm -f "$PID_FILE"
        fi
    else
        echo "Tomcat 未运行,未找到 PID 文件。"
    fi
}


status() {
    if [ -f "$PID_FILE" ] && [ -s "$PID_FILE" ]; then
        PID=$(cat "$PID_FILE")
        if ps -p $PID > /dev/null 2>&1; then
            echo "Tomcat 正在运行,进程号:$PID"
        else
            echo "PID 文件存在,但进程 $PID 不存在。"
        fi
    else
        echo "Tomcat 未运行。"
    fi
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        start
        ;;
    status)
        status
        ;;
    *)
        echo "使用方法:$0 {start|stop|restart|status}"
        exit 1
        ;;
esac

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XingYuyu_Coder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值