记一次linux上的僵死进程排查

anonymous_vhacker
anonymous_vhacker
发布于 2023-07-07 / 46 阅读
1
0

记一次linux上的僵死进程排查

前言

有一天,发现自己的 All in boom All in one 云服务器时不时在登录的时候提示由很多僵死进程(如下图所示),就觉得很奇怪。

这东西虽然吧,截至目前暂时没有引发什么服务停止运作;但是吧,看着总是慌慌的,存在一定的隐患,让人有一种”你现在不能休息,周围有怪物在游荡“的感觉。所以,觉得还是尽量避免出现僵死进程比较好,于是就进行了排查。

什么是僵死进程

僵死进程(defunct),又叫孤儿进程(orphan process)。

当fork一个新进程的时候,子进程一般会和父进程同时运行。当子进程结束的时候,它与父进程的关联还会保持,直到父进程也正常终止或者wait,子进程才结束。因此,进程中代表子进程的表项不会立即释放。虽然子进程已经不能正常运行,但是它仍然存在于系统之中,因为它的退出码还要保存起来,以备父进程今后的wait调用使用。

这种情况我们称已经结束了但是还不能释放的子进程为僵死进程。僵死进程不能用kill -9杀死(本来都是死的了,怎么再死)。

虽然僵进程已经是死的了,但是它在进程表(processs table)中仍占了一个位置(slot)。僵死进程会占用系统资源,如果系统有太多的僵死进程,当PID耗尽的时候,可能出现不能再启动其他进程,甚至导致系统崩溃。所以要尽量避免僵死进程的产生。

问题定位

1. 先找到是哪些僵死进程

ps aux | grep "Z"

输出:

一堆[git]进程,孤儿进程,找找他爹是谁,竟然无情的抛下他的孩子们。

2. 找父进程

抓一个孤儿进程过来,问问他爹是谁,就抓pid为 873128 的这个吧,如下命令:

ps -ef | grep 873128

pid有两列,左边这列是进程的pid,右边这列是父进程的pid,找到他的父进程pid为1909。

3. 继续溯源:

ps -ef | grep 1909

image-cfbz.png

找到一个名为node的进程,这个进程就是元凶了,产生了好多孤儿进程。

但为了更加进一步的找到问题的根本,不能把这个进程杀掉草草了事,得查明元凶背后的主使。继续溯源:

ps -ef | grep 1555

找到是一个docker容器跑的进程。我的机器上跑着很多docker容器,要查一查到底是哪个容器搞的鬼。

docker ps

根据上面的进程信息,可以确定是这个名为jd的容器搞的鬼。

问题解决

查询之后,发现是因为这个容器用node.js作为初始化进程导致的。node.js官方也提到,不建议在docker中作为PID 1来启动。(原文连接

解决办法是,在启动容器的时候,加上--init参数,这样可以用docker的init进程作为初始化进程。希望这样,能让docker的init照管好这些”孤儿“们。

docker stop jd

docker container rm jd

docker run -itd --init --name jd \
>     --restart always \
>     -v jd_base:/jd \
>     -e ENABLE_HANGUP=true \
>     -e ENABLE_WEB_PANEL=true \
>     --network host \
>     shuye72/jd-base:gitee

总结

  1. 找到僵死进程。

  2. 找到父进程。

  3. 找到父进程的问题根源。

  4. docker中以node.js为初始化进程所致。

  5. 关闭并删除容器,加上--init参数来重新启动容器。


评论