神奇的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进程是指出错损坏的进程,父子进程之间不会再通信.有时,它们会演变成“僵尸进程”,存留在你 ...
随机推荐
- docker 搭建小型的node开发环境。
选择daocloud的镜像源----快.不多说 镜像的准备: docker pull docker.io/node 下载node镜像 docker pull daocloud.io/nginx 下载n ...
- (转)java程序调用内存变化过程分析(详细)
原博地址: https://blog.csdn.net/Myuhua/article/details/81385609 (一)不含静态变量的java程序运行时内存变化过程分析 代码: package ...
- Android-隐藏app图标以及隐式启动
隐藏APP桌面图标 <activity android:name=".LaunchActivity"> <intent-filter> <action ...
- FreeSql (二十三)分组、聚合
IFreeSql fsql = new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.MySql, "Data ...
- Slickflow.NET 开源工作流引擎快速入门之三: 简单或分支流程代码编写示例
前言:对于急切想了解引擎功能的开发人员,在下载版本后,就想尝试编写代码,完成一个流程的开发和测试.本文试图从请假流程,或分支模式来快速了解引擎代码的编写. 1. 创建或分支流程图形 或分支流程是常见的 ...
- java生成二维码/java解析二维码
二维码的优缺点 优点:1. 高密度编码,信息容量大:2.编码范围广:3.容错能力强:4.译码可靠性高:5.可引入加密措施:6.成本低,易制作,持久耐用. 缺点:1.二维码技术成为手机病毒.钓鱼网站传播 ...
- 超实用的SQL语句之嵌套查询
嵌套查询 什么是嵌套查询 . 嵌套查询的意思是,一个查询语句(select-from-where)查询语句块可以嵌套在另外一个查询块的where子句中,称为嵌套查询.其中外层查询也称为父查询,主查询. ...
- 提交任务到spark(以wordcount为例)
1.首先需要搭建好hadoop+spark环境,并保证服务正常.本文以wordcount为例. 2.创建源文件,即输入源.hello.txt文件,内容如下: tom jerry henry jim s ...
- Mybatis逆向工程过程中出现targetRuntime in context mybatisGenerator is invalid
最开始设置的Mybatis,但是逆向工程准备就绪后出现问题 报错为targetRuntime in context mybatisGenerator is invalid 后来修改为Mybatis3能 ...
- WPF 将字体文件 添加到 资源文件,并在后台代码使用
先看结果 1.将字体文件,导入到资源文件,如: 添加后,自动生成 2.在窗体xaml中添加如: 3.在xaml窗体对应的cs文件中,为TextBlock指定字段 创建一个字段对象,并指定字体文件的所在 ...