神奇的Java僵尸(defunct)进程问题排查过程
现象描述
大概1个月多以前 在启动脚本中增加了tail -f
用来启动后追踪日志判断是否启动成功
后发现无法执行shutdown.sh(卡住 利用curl) 然后无奈使用kill -9
但通过ps -el 发现此时进程变为defunct 即僵尸进程
当时的解决办法无奈 只能找到僵尸进程的父进程kill
当时认为可能是tail的问题 后来启动脚本中去掉tail 发现问题解决
But
当时一直没有来得及排查是如何引起僵尸进程的问题
这两天抽时间排查了一下 发现和tail没有一毛钱关系
艰难的排查过程1-尝试复现
测试代码Defunct.java

启动脚本start.sh

启动脚本start_tail.sh 使用了tail

关服脚本stop.sh 这里使用kill关服

分别用两个脚本测试,得出下面几个结论:
所以初步结论是貌似和tail没有什么关系
此时sh和tail两个进程都结束了
而此时java进程的父进程变为了1
sh分别有两个子进程
一个是java子进程 一个是tail子进程
start.sh启动的java进程的父进程是1 即init进程
start_tail.sh启动后 java进程的父进程是sh
当启动start_tail.sh后 因为tail是前台进程 所以ctrl+c可以结束
用这个例子做各种测试 都无法复现僵尸进程的问题
艰难的排查过程2-游戏服务器尝试复现
当初出现是在游戏服务器复现的 那么应该比较复现吧
修改了一个游戏服务器的启动脚本 默认是没有加tail 现在加上了tail -f
启动游戏服务器脚本 看到日志 启动成功 ctrl+c 退出tail
调用shutdown.sh 发现服务器顺利关闭
结论:竟然无法在游戏服务器复现
艰难的排查过程3-各种思考、查阅资料
首先从僵尸进程的产生原因入手,猜测是否是sh这个父进程没有调用waitpid去回收java子进程。
查询网上类似的tomcat tail -f问题,思考当初1个多月以前的情形,其中有一个很重要的当初情形是shutdown的时候ctrl卡住了。灵光一现,难道是当初操作失误了,没有按下ctrl+c而是按下了ctrl+z。
神奇的ctrl+z 复现测试代码defunct
启动start_tail.sh 然后ctrl+z

启动stop.sh 发现进程(3974)无法被stop

使用kill -9 尝试杀死进程 此时发现进程已经是defunct了

此时只要使用fg命令从后台调到前台然后按下ctrl+c 则僵尸进程自动消失

神奇的ctrl+z 复现游戏服务器defunct
启动脚本(有tail) 等待一段时间(将所有服务器全部开启) 并ctrl+z

此时执行shutdown.sh 发现没有任何反应(卡住) 无奈ctrl+c

此时执行jstack 也发现没有任何反应(卡住) 无奈ctrl+c

此时执行kill -9 此时java进程已经变为了僵尸进程

此时用fg将暂停的脚本恢复 然后ctrl+c 则僵尸进程消失 顺利被回收

总结1
tail和造成defunct没有任何关系
根本原因是因为按下ctrl+z 将start_tail.sh切换到了后台
测试1 当start_tail.sh后 按下ctrl+z 如果直接被crt#session关闭了呢
更神奇的事情发生了 java进程直接被干掉了
!!这个在游戏服务器也测试了 一定要注意!!
测试2 执行start_tail.sh 直接关闭ctr#session 则java进程还在 因为是nohup启动
测试3 当start_tail.sh后 按下ctrl+z 再按fg 恢复执行 此时之后可以顺利shutdown
总结2
正常启动脚本 没有tail java进程的父进程是1 即init进程 使用shutdown脚本关闭java进程后 自动被init进程回收
启动脚本加了tail
此时java进程的父进程是sh进程
sh进程有两个子进程 一个是java子进程 一个是tail子进程
直接ctrl+c 则sh进程和tail进程都结束 java进程的父进程变为了1
如果不ctrl+c 直接shutdown java进程 则java进程也会正常结束,即sh父进程会回收java子进程
总结3
最终'罪魁祸首'是ctrl+z ,它会暂停程序的运行
如果我们启动脚本没有加tail 则执行完nohup & 自动到后台
但是我们加了tail后 因为tail是前台进程 所以要么ctrl+c结束 要么ctrl+z
如果我们按下了ctrl+z 则sh启动的所有子进程都会暂停
所以我们的java进程此时处于暂停状态 所以shutdown/jstack都卡住了一样 只能ctrl+c退出
然后错误的操作就是使用kill -9 这个会把进程给干掉 但是因为父进程sh被暂停了 所以无法waitPid 执行子进程的回收操作 从而导致java进程变为了僵尸进程
而通过fg恢复后 ctrl+c 父进程和tail都退出 java进程被init进程接管 自动回收
总结4
加tail -f 没有问题,但是一定不要忘了ctrl+c;
如果ctrl+z 那么一定要fg然后ctrl+c;
当出现shutdown.sh卡住或者操作jvm都没反应,则可以怀疑是暂停引起的;
————————————
原文链接:https://www.jianshu.com/u/21add3dce532
神奇的Java僵尸(defunct)进程问题排查过程的更多相关文章
- 僵尸进程的产生和避免,如何kill杀掉linux系统中的僵尸defunct进程
在 Unix系统管理中,当用ps命令观察进程的执行状态时,经常看到某些进程的状态栏为defunct,这就是所谓的"僵尸"进程."僵尸"进程是一个早已 死亡的进程 ...
- 【转】Defunct进程 僵尸进程
在测试基于 DirectFB+Gstreamer 的视频联播系统的一个 Demo 的时候,其中大量使用 system 调用的语句,例如在 menu 代码中的 system("./play&q ...
- <转>杜绝 Defunct进程 僵尸进程
http://hanover.iteye.com/blog/881972 在测试基于 DirectFB+Gstreamer 的视频联播系统的一个 Demo 的时候,其中大量使用 system 调用的语 ...
- Linux中的defunct进程(僵尸进程)
一.什么是defunct进程(僵尸进程)?在 Linux 系统中,一个进程结束了,但是他的父进程没有等待(调用wait / waitpid)他,那么他将变成一个僵尸进程.当用ps命令观察进程的执行状态 ...
- 杀死Linux中的defunct进程(僵尸进程)的方法指南
杀死Linux中的defunct进程(僵尸进程)的方法指南_LINUX_操作系统_脚本之家https://www.jb51.net/LINUXjishu/457748.html 这样能看到僵尸进程.
- Kill杀死Linux中的defunct进程(僵尸进程)
一.什么是defunct进程(僵尸进程)? 在 Linux 系统中,一个进程结束了,但是他的父进程没有等待(调用wait / waitpid)他,那么他将变成一个僵尸进程.当用ps命令观察进程的执行状 ...
- JAVA程序CPU 100%问题排查
做JAVA开发的同学一定遇到过的爆表问题,看这里解决 https://www.cnblogs.com/qcloud1001/p/9773947.html 本文由净地发表于云+社区专栏 记一次Ja ...
- (转)[sh] <defunct>进程
我也碰到僵尸进程了,必须通过关闭僵尸进程的父进程或者重启解决. 来自:http://jerrybear.blog.51cto.com/629421/387846 今日发现服务器上多了一些名称为[sh] ...
- 如何杀死defunct进程
原文: How to kill defunct process 译者: youngsterxyf defunct进程是指出错损坏的进程,父子进程之间不会再通信.有时,它们会演变成“僵尸进程”,存留在你 ...
随机推荐
- Dapper学习(二)之Query相关
0. FIrst , Single & Default 使用这个方法时要小心,First 和 Single 是不同的. 这里,对这个表做下说明: 如果使用 First , 当没有查到元素时,会 ...
- javase复习(一)
break,continue,return区别: continue:跳出本次循环,还要再执行下次循环 break:跳出循环,若有多层循环则只跳出本层循环,其他层的循环需要挨个break return: ...
- FreeSql (七)插入数据时忽略列
var connstr = "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;" + "Initia ...
- JSP静态include和动态include的区别
静态include是指令元素.include指令的语法格式:<%@ include file="filename" %>.include指令的作用是在JSP页面中静态包 ...
- java工作流快速开发之授权代办的设计
关键词:工作流快速开发平台 工作流流设计 业务流程管理 Java工作流引擎 asp.net 开源工作流 net开源工作流引擎 开源工作流系统 一.授权代办开发背景 应用需求:项目审批人出差无法及 ...
- Sqoop介绍、安装与操作
搭建环境 部署节点操作系统为CentOS,防火墙和SElinux禁用,创建了一个shiyanlou用户并在系统根目录下创建/app目录,用于存放 Hadoop等组件运行包.因为该目录用于安装hadoo ...
- 以商品超卖为例讲解Redis分布式锁
本案例主要讲解Redis实现分布式锁的两种实现方式:Jedis实现.Redisson实现.网上关于这方面讲解太多了,Van自认为文笔没他们好,还是用示例代码说明. 一.jedis 实现 该方案只考虑R ...
- charles 镜像工具
本文参考:charles 镜像工具 镜像工具会在你浏览指定网站时,把抓取到的文件克隆一份,并保存在你指定的路径下: 注意:如果你配置是www.aaa.com; 那么只会抓这个域名下的文件,这个域名如果 ...
- 浅谈@RestController和@Controller的区别
在做Spring MVC开发时,如果对@RestController或者@Controller这两个注解理解不够清晰的话,就难免会出现用混的情况.而混用的结果往往是无法实现期望的跳转结果或者是直接将跳 ...
- BeanFactory not initialized or already closed
产生这个错误有两个可能, 一.你没有配置初始化文件,在web.xml中配置如下 <context-param> <param-name>contextConfigLocatio ...