阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Linux中Tomcat shutdown.sh后进程仍然存在解决办法

137次阅读
没有评论

共计 7003 个字符,预计需要花费 18 分钟才能阅读完成。

最近我们在使用 Jenkins 自动化部署项目时,在生产 liunx 环境下,使用脚本 shutdown.sh 停止 tomcat 服务,然后再 start 之后发现应用无法访问了,后台查看 tomcat 进程是发现有个 2 个 tomcat 进程,说明之前的 shutdown 并没有完全停掉 tomcat 进程。那怎么样 tomcat 使用 shutdown 之后立马关掉其进程呢?经查资料发现在 shutdown.sh 脚本之后有条命令是这样的:

exec “$PRGDIR”/”$EXECUTABLE” stop “$@” 这个就是停止 tomcat 服务的命令,我们只需要加一个  -force  就可以在 shutdown 时强制关闭 tomcat 进程

exec “$PRGDIR”/”$EXECUTABLE” stop -force “$@”

但光这样还是不行,再 shutdown 时报错:

Kill failed: $CATALINA_PID not set 查找失败原因:

+ FORCE=1
+ ‘[‘ ‘!’ -z ” ‘]’
+ /usr/java/jdk1.6.0_38/bin/java -server -Xms2048m -Xmx2048m -Xmn768m -XX:PermSize=128m -XX:MaxPermSize=256m -XX:+UseParallelOldGC -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/xrltest1/tomcat/dumpfile/heap.bin -Xloggc:/home/xrltest1/tomcat/logs/gc.log -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/home/xrltest1/tomcat/endorsed -classpath /home/xrltest1/tomcat/bin/bootstrap.jar -Dcatalina.base=/home/xrltest1/tomcat -Dcatalina.home=/home/xrltest1/tomcat -Djava.io.tmpdir=/home/xrltest1/tomcat/temp org.apache.catalina.startup.Bootstrap stop
2015-3-21 11:59:53 org.apache.catalina.startup.Catalina stopServer
严重: Catalina.stop:
java.net.ConnectException: Connection refused
  at java.net.PlainSocketImpl.socketConnect(Native Method)
  at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
  at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
  at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
  at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
  at java.net.Socket.connect(Socket.java:529)
  at java.net.Socket.connect(Socket.java:478)
  at java.net.Socket.<init>(Socket.java:375)
  at java.net.Socket.<init>(Socket.java:189)
  at org.apache.catalina.startup.Catalina.stopServer(Catalina.java:422)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  at java.lang.reflect.Method.invoke(Method.java:597)
  at org.apache.catalina.startup.Bootstrap.stopServer(Bootstrap.java:338)
  at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:416)
+ ‘[‘ ‘!’ -z ” ‘]’
+ ‘[‘ 1 -eq 1 ‘]’
+ ‘[‘ -z ” ‘]’
+ echo ‘Kill failed: $CATALINA_PID not set’
Kill failed: $CATALINA_PID not set
从中可以看到,首先是执行 java 命令失败,没有停止 tomcat,然后执行 -force 模块的命令,但是却没有找到 $CATALINA_PID 设定的进程号,我们先不去关注 java 执行 stop 命令为什么报错,而是看看为什么加了 -force 参数也不起作用了

为什么没有 $CATALINA_PID?接下来就带大家一探究竟

首先,我们将涉及到 $CATALINA_PID 变量的代码全部提取出来:

第一处:

# 以下这句判断设置的 $CATALINA_PID 变量如果不存在,则显示 ”Using CATALINA_PID:

 $CATALINA_PID”,如果存在则不显示
  if [! -z “$CATALINA_PID”]; then
    echo “Using CATALINA_PID:    $CATALINA_PID”
  fi
fi# 貌似只是判断 $CATALINA_PID 是否是空字符,其他什么都没有做

第二处:(涉及到 start 参数的模块内的 $CATALINA_PID 变量,只是提出来分析,其实不对 stop 模块有影响)

        #这个是 start 模块内的代码
“$_RUNJAVA” “$LOGGING_CONFIG” $JAVA_OPTS $CATALINA_OPTS \
  -Djava.endorsed.dirs=”$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
# 判断 CATALINA_PID 如果不是空字符,则将 Shell 最后运行的后台 Process 的 PID 传给 $CATALINA_PID
echo $! > “$CATALINA_PID”
# 在使用命令运行进程至后台时,可以使用 $! 抓取前面启动运行在后台进程的进程号
fi
fi
# 上面语句是 tomcat 在启动时,会将 $CATALINA_PID 写入 PID 进程号第三处:

# 一下语句都出现在 stop 模块内
if [! -z “$CATALINA_PID”]; then
#$CATALINA_PID 文件不是非空
  if [-f “$CATALINA_PID”]; then
    if [-s “$CATALINA_PID”]; then
      kill -0 `cat “$CATALINA_PID”` >/dev/null 2>&1
#kill -0 pid 不发送任何信号,但是系统会进行错误检查。
      if [$? -gt 0]; then
        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
# 如果发现 $CATALINA_PID 则发送一个模拟结束进程的型号,如果返回值为 0,则正常,其他则异常,做退出操作

# 从上面的 sh - x 输出的信息对应的是:'[‘ ‘!’ -z ” ‘]’ 可以看出 $CATALINA_PID 变量没有设定,所以这个判断直接就结束了,什么都没做

第四处:

  #下面的代码紧接着 stop 的正常停止代码下
  if [! -z “$CATALINA_PID”]; then
  #如果 $CATALINA_PID 不为空
    if [-f “$CATALINA_PID”]; then
# 而且还是普通文件
      while [$SLEEP -ge 0]; do
  #而且 $SLEEP 还大于 0
        kill -0 `cat “$CATALINA_PID”` >/dev/null 2>&1
# 则测试下 tomcat 能不能被关闭
        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”
            else
              echo “Tomcat stopped but the PID file could not be removed or cleared.”
            fi
          fi
          break
        fi
        if [$SLEEP -gt 0]; then
          sleep 1
        fi
        if [$SLEEP -eq 0]; then
          if [$FORCE -eq 0]; then
            echo “Tomcat did not stop in time. PID file was not removed.”
          fi
        fi
        SLEEP=`expr $SLEEP – 1 `
      done
    fi
  fi
  #上段语句主要是判断 tomcat 是否被关闭
  #核心语句还是:kill -0 `cat “$CATALINA_PID”` >/dev/null 2>&1
  #while 语句做 sleep 使用,用于清空 $CATALINA_PID
  #但是[! -z “$CATALINA_PID”] 导致这段语句什么都没做啊!!!!!第五处:

 #这段代码就是涉及 -force 的核心代码了
  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
# 强制执行的核心命令
        rm -f “$CATALINA_PID” >/dev/null 2>&1
        if [$? != 0]; then
          echo “Tomcat was killed but the PID file could not be removed.”
        fi
      fi
    fi
  fi
# 从中就可以看出,sh - x 输出的 Kill failed: $CATALINA_PID not set 是怎么来的总结下,$CATALINA_PID 在整个代码中的作用:

1. 在 tomcat 启动时会写入 $CATALINA_PID,但是假设我们的环境是多 tomcat 项目或 $CATALINA_PID 为空

2.stop 代码中,检查 $CATALINA_PID 是否为空字符,是的话什么都不做

3.sstop 代码中,检查 $CATALINA_PID 是否为空字符,是的话什么都不做

4.force 代码中,检查 $CATALINA_PID 是否为空字符,是的话就报错

也就是说只要没有保存中这个项目的 PID,那么正常 stop 停止不了,-force 也是没有用的。

那么该如何解决呢?直接给 $CATALINA_PID 付 PID 的值,那么看结果:

+ FORCE=1
+ ‘[‘ ‘!’ -z 12031 ‘]’
+ ‘[‘ -f 12031 ‘]’
+ echo ‘$CATALINA_PID was set but the specified file does not exist. Is Tomcat running? Stop aborted.’
$CATALINA_PID was set but the specified file does not exist. Is Tomcat running? Stop aborted. 涉及到的代码:

if [-f “$CATALINA_PID”]; then
  if [-s “$CATALINA_PID”]; then
kill -0 `cat “$CATALINA_PID”` >/dev/null 2>&1
#kill -0 pid 不发送任何信号,但是系统会进行错误检查。
if [$? -gt 0]; then
  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
 #$CATALINA_PID 不是个文件,所以不好意思,我退出了 …. 原来 $CATALINA_PID 还必须是个文件,那么我们可不可以建这么一个文件呢?

在 catalina.sh 脚本的代码前,加入以下语句:

#########################################################################################
if [-z “$CATALINA_PID”]; then
    CATALINA_PID=$PRGDIR/CATALINA_PID
    cat $CATALINA_PID
fi###################################################################################### 结果:tomcat 停止执行成功,完成结束进程任务

总结:
在我看到的很到部署 tomcat 的文章中,还没发现有关于设置 $CATALINA_PID��件路径的提示(也许是我看到的少),但是此处我要建议小伙伴们,在写 tomcat 启动、停止、重启的脚本的时候,一定要注意这个变量。

更多 Tomcat 相关教程见以下内容

CentOS 6.6 下安装配置 Tomcat 环境  http://www.linuxidc.com/Linux/2015-08/122234.htm

RedHat Linux 5.5 安装 JDK+Tomcat 并部署 Java 项目  http://www.linuxidc.com/Linux/2015-02/113528.htm 

Tomcat 权威指南(第二版)(中英高清 PDF 版 + 带书签)  http://www.linuxidc.com/Linux/2015-02/113062.htm 

Tomcat 安全配置与性能优化 http://www.linuxidc.com/Linux/2015-02/113060.htm 

Linux 下使用 Xshell 查看 Tomcat 实时日志中文乱码解决方案 http://www.linuxidc.com/Linux/2015-01/112395.htm 

CentOS 64-bit 下安装 JDK 和 Tomcat 并设置 Tomcat 开机启动操作步骤 http://www.linuxidc.com/Linux/2015-01/111485.htm 

CentOS 6.5 下安装 Tomcat  http://www.linuxidc.com/Linux/2015-01/111415.htm 

Tomcat 的详细介绍:请点这里
Tomcat 的下载地址:请点这里

本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-09/134952.htm

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-21发表,共计7003字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中