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

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

#!/bin/bash
cd /usr/software/tomcat/apache-tomcat-7.0.81/bin/
./catalina.sh start
tail -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/bash
cd /usr/software/tomcat/apache-tomcat-7.0.81/bin/
./catalina.sh start

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

#!/bin/bash
set -m
cd /usr/software/tomcat/apache-tomcat-7.0.81/bin/
./catalina.sh start
tail -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/bash
set -m
cd /usr/software/tomcat/apache-tomcat-7.0.81/bin/
./catalina.sh start
tail -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进程就不是他们的子进程了,自然怎么操作都不会受影响。

Tomcat意外宕机分析的更多相关文章

  1. 修复ogg source端意外宕机造成的数据不同步

    修复ogg source端意外宕机造成的数据不同步 分类: Oracle2016-04-28 11:50:40原文地址:修复ogg source端意外宕机造成的数据不同步 作者:十字螺丝钉 ogg s ...

  2. linux服务器宕机分析/性能瓶颈分析

    linux服务器宕机分析/性能瓶颈分析   服务器宕机原因很多,资源不足.应用.硬件.系统内核bug等,以下一个小例子 服务器宕机了,首先得知道服务器宕机的时间点,然后分析日志查找原因 1.last ...

  3. tomcat服务器宕机解决方案

    报错信息: java.lang.Object.wait(Native Method) java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:1 ...

  4. HBase–RegionServer宕机恢复原理

    Region Server宕机总述 HBase一个很大的特色是扩展性极其友好,可以通过简单地加机器实现集群规模的线性扩展,而且机器的配置并不需要太好,通过大量廉价机器代替价格昂贵的高性能机器.但也正因 ...

  5. 【JVM】linux上tomcat中部署的web服务,时好时坏,莫名其妙宕机,报错:There is insufficient memory for the Java Runtime Environment to continue.

    =========================================================================================== 环境: linu ...

  6. ORA-04031错误导致宕机案例分析

    今天遇到一起ORACLE数据库宕机案例,下面是对这起数据库宕机案例的原因进行分析.解读.分析过程中顺便记录一下这个案例的前因后果,攒点经验值,培养一下分析.解决问题的能力. 案例环境:   操作系统 ...

  7. Solr4.8.0源码分析(26)之Recovery失败造成的宕机原因分析

    最近在公司做SolrCloud的容灾测试,刚好碰到了一个比较蛋疼的问题,跟SolrCloud的Recovery和leader选举有关,正好拿出来分析下. 现象是这样的:比如我有一台3个shard的So ...

  8. 关于解决Tomcat服务器Connection reset by peer 导致的宕机

    org.apache.catalina.connector.ClientAbortException: java.io.IOException: Connection reset by peer at ...

  9. 网络流量分析——NPMD关注IT运维、识别宕机和运行不佳进行性能优化。智能化分析是关键-主动发现业务运行异常。科来做APT相关的安全分析

    科来 做流量分析,同时也做了一些安全分析(偏APT)——参考其官网:http://www.colasoft.com.cn/cases-and-application/network-security- ...

随机推荐

  1. Oracle通过序列+触发器实现主键自增

    接触oracle没多久,在建表的时候发现还不会如何设置主键自动增长.和mysql的设置为AUTO_INCREMENT属性相比,要复杂很多,所以现在记录起来. 我使用的是序列+触发器的方式. 现在已经创 ...

  2. 高性能mysql-锁的调试

    锁的调试分为俩部分,一是服务器级别的锁的调试.二是存储引擎级别的锁的调试 对于服务器级别的锁的调试: 服务器级别的锁的类型有表锁,全局锁,命名锁,字符锁 调试命令: Show processlist ...

  3. [.net core学习] .net core中的Rijndael取代方法

    The difference (in .NET) between Rijndael and AES is that Rijndael allows the block size to change, ...

  4. Mybatis中输入输出映射和动态Sql

    一.输入映射 我们通过配置parameterType的值来指定输入参数的类型,这些类型可以是简单数据类型.POJO.HashMap等数据类型 1.简单类型 2.POJO包装类型 ①这是单表查询的时候传 ...

  5. Codeforces gym102152 K.Subarrays OR

    传送:http://codeforces.com/gym/102152/problem/K 题意:给定$n(n\le10^5)$个数$a_i(a_i\le10^9)$,对于任一个子数组中的数进行或操作 ...

  6. log4j 详细使用教程【转载】

    日志是应用软件中不可缺少的部分,Apache的开源项目log4j是一个功能强大的日志组件,提供方便的日志记录.在apache网站:jakarta.apache.org/log4j 可以免费下载到Log ...

  7. 机器学习与Tensorflow(6)——LSTM的Tensorflow实现、Tensorboard简单实现、CNN应用

    最近写的一些程序以及做的一个关于轴承故障诊断的程序 最近学习进度有些慢 而且马上假期 要去补习班 去赚下学期生活费 额.... 抓紧时间再多学习点 1.RNN递归神经网络Tensorflow实现程序 ...

  8. Pycharm 连接Linux 远程开发

    Pycharm 连接Linux 远程开发 在Liunx上安装python3.6(Ubuntu16) 下载Python-3.6.4.tgz 解压 tar -xzvf Python-3.6.4.tgz 进 ...

  9. Java gc中的那些事

    我们已经知道Java堆是被所有线程共享的一块内存区域,所有对象实例和数组都在堆栈进行内存分配.为了进行高效的垃圾回收,虚拟机把堆内存划分成新生代年代(旧一代)和永久代(永久代)3个区域. 新生代 新生 ...

  10. php 判断客户端是否为手机端访问

    function is_mobile_request() { $_SERVER['ALL_HTTP'] = isset($_SERVER['ALL_HTTP'])?$_SERVER['ALL_HTTP ...