日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java 僵尸进程_神奇的Java僵尸(defunct)进程问题排查过程

發布時間:2024/3/13 java 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 僵尸进程_神奇的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 僵尸进程_神奇的Java僵尸(defunct)进程问题排查过程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。