博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Tomcat意外宕机分析
阅读量:6922 次
发布时间:2019-06-27

本文共 2388 字,大约阅读时间需要 7 分钟。

  之前在网上看过一篇文章,是讲的,我看完感觉好奇,自己也测试了下,果然是有这种问题,所以自己也借此总结一下。

  先简单说下测试过程,先创建一个web服务启动 test.sh,内容如下:

#!/bin/bashcd /usr/software/tomcat/apache-tomcat-7.0.81/bin/./catalina.sh starttail -f /usr/software/tomcat/apache-tomcat-7.0.81/logs/catalina.out

  然后启动该脚本,服务起来了,可以正常访问。

  tomcat启动之后,当前shell进程并没有退出,而是挂住在tail进程,往终端输出日志内容。这种情况下:

  1)、如果我先直接关掉ssh窗口后,Java进程会退出,服务不可用。

  2)、而我如果先 用ctrl-c终止test.sh进程,然后再关闭ssh终端的话,这时Java进程不会退出。服务没有受到影响,仍然可用。

  3)、下面我又把最后tail这一行去掉,发现直接关掉ssh终端窗口,Java进程也不会退出,服务不受影响。

#!/bin/bashcd /usr/software/tomcat/apache-tomcat-7.0.81/bin/./catalina.sh start

  4)、最后我再次恢复tail这一行,然后在开头再加上 set -m, 直接关掉ssh窗口Java进程同样也不会退出,服务同样也不受影响。

#!/bin/bashset -mcd /usr/software/tomcat/apache-tomcat-7.0.81/bin/./catalina.sh starttail -f /usr/software/tomcat/apache-tomcat-7.0.81/logs/catalina.out

  到这里是不是有点晕了,不急,待我慢慢道出原因来。

 

  这是一个有趣的现象,catalina.sh start方式启动的tomcat会把java进程挂到init(进程id为1)的父进程下,已经与当前test.sh进程脱离了父子关系,也与ssh进程没有关系,为什么关闭ssh终端窗口会导致java进程退出?

  经过测试,有发现:

  a) 用 ctrl-c 终止当前test.sh进程时,系统events进程向 java 和 tail 两个进程发送了SIGINT 信号

  b) 关闭ssh终端窗口时,sshd向下游进程发送SIGHUP, java进程也会收到。

  后来通过google后了解到: shell在非交互模式下对后台进程处理SIGINT信号时设置的是IGNORE

  交互模式与非交互模式对作业控制(job control)默认方式不同:

  I)在交互模式下,因为作业控制的需要shell不会对后台进程处理SIGINT信号设置为忽略。因此这样的话,父进程会把收到的键盘事件比如ctrl-c之类的SIGINT传播给进程组中的每个成员(假设后台进程也是父进程组的成员),那么终端随意ctrl-c就可能导致所有的后台进程退出,显然这样是不合理的。因此,在交互模式下的后台进程会设置一个自己的进程组ID。

  II)而非交互模式下,通常是不需要作业控制的,所以作业控制在非交互模式下默认也是关闭的(当然也可以在脚本里通过选项set -m打开作业控制选项)。不开启作业控制的话,脚本里的后台进程可以通过设置忽略SIGINT信号来避免父进程对组中成员的传播,因为对它来说这个信号已经没有意义。

  在非交互模式下,shell对java进程设置了SIGINTSIGQUIT信号设置了忽略,但并没有对SIGHUP信号设为忽略,回头看上面说的,直接关闭ssh终端窗口时,sshd向下游进程发送SIGHUP, java进程也会收到。

  再看一下当时的进程层级:

 

  |-sshd(1622)-+-sshd(11681)---sshd(11699)---bash(11700)---test.sh(13285)---tail(13299)   

  sshd把SIGHUP传递给bash进程后,bash会把SIGHUP传递给它的子进程,并且对于其子进程test.sh,bash还会对test.sh的进程组里的成员都传播一遍SIGHUP。因为java后台进程从父进程catalina.sh(又是从其父进程test.sh)继承的pgid,所以java进程仍属于test.sh进程组里的成员,收到SIGHUP后退出。

  如果我们在test.sh里设置开启作业控制的话,就不会让java进程退出了

#!/bin/bashset -mcd /usr/software/tomcat/apache-tomcat-7.0.81/bin/./catalina.sh starttail -f /usr/software/tomcat/apache-tomcat-7.0.81/logs/catalina.out

  此时java后台进程继承父进程catalina.sh的pgid,而catalina.sh不再使用test.sh的进程组,而是自己的pid作为pgid,catalina.sh进程在执行完退出后,java进程挂到了init下,java与test.sh进程就完全脱离关系了,bash也不会再向它发送信号。

  

  注: 如果把tail 打印的这一行去掉,为什么Java进程也不会退出,我猜原因应该是,如果没有tail的话, Java进程就不是他们的子进程了,自然怎么操作都不会受影响。

 

转载于:https://www.cnblogs.com/xiexin2015/p/9032510.html

你可能感兴趣的文章
英伟达为Jetson Xavier提供Isaac智能机器人平台
查看>>
Linux基础:逻辑卷管理器详解(LVM)
查看>>
浅析工厂企业培养TPM设备管理员必备的三大要素
查看>>
开运联合智慧畜牧平台助力传统畜牧转型升级
查看>>
java基础概念
查看>>
C++编写的一个简单的猜数字游戏源码
查看>>
转:javaweb开发超时设置
查看>>
ubunut 15.04 新手初尝试
查看>>
iOS开发系列--通讯录、蓝牙、内购、GameCenter、iCloud、Passbook系统服务开
查看>>
redhat5下的×××搭建
查看>>
服务器×××上的MSDTC不可用解决办法
查看>>
深入探索spring技术内幕(四): 剖析@Resource注解实现原理与注解注入
查看>>
tr 的用法
查看>>
了解注解
查看>>
Storm 集群异常的解决
查看>>
Cpp:int_tmain()和main()有什么区别
查看>>
Centos升级python到2.6
查看>>
GlusterFS in CentOS 6.5的实现和配置
查看>>
25幅难以置信的世界各地摄影作品欣赏
查看>>
60套漂亮的的免费 PSD 界面设计元素包资源(系列二)
查看>>