Ubuntu容器中的僵尸进程

问题简介

我所在项目组,在Windows系统上安装Docker Desktop软件,基于Ubuntu系统镜像搭建开发环境,用以开发运行于Linux环境下的程序。

leader负责搭建开发环境,在搭建好开发环境之后,使用 docker export 导出镜像文件,再由我使用 docker import 导入镜像文件。

我在该开发环境编译好应用程序之后使用 gdb 调试,退出 gdb 调试之后再次启动 gdb 进行调试,应用程序提示已有实例在运行无法启动。

查看应用程序代码,发现应用程序使用 ps 命令检查是否有重复实例在运行,原来是应用程序根据业务需要来避免多实例运行。

使用 ps 命令查看,发现 gdb 和应用程序的进程状态为僵死状态,也就是说退出 gdb 调试之后 gdb 和应用程序变成了僵尸进程。

首先尝试使用 kill 命令杀死僵尸进程,发现并不能将其杀死。在网上搜索杀死僵尸进程的方法,也未能搜索到行之有效的方法。

由于开发环境的镜像文件来至于leader,遂向leader询问是否存在相同的问题,leader操作了一番之后发现并没有出现相同的问题。

我猜测可能是由于使用的代码分支不一致导致的,遂将代码分支切换到和leader一样,重新编译之后使用 gdb 调试发现退出调试时仍然存在僵尸进程。

既然不是代码的问题,我就怀疑是由于开发环境导致的,在网上搜索了下僵尸进程产生的原因,发现僵尸进程会被init进程收养后再销毁。

使用 ps 命令查看并未发现名为 init 的进程,不过发现进程号为 1 的进程是 /bin/sh。

对比leader开发环境发现在他的容器中,进程号为 1 的进程不是 /bin/sh 而是 /bin/bash。

使用 ls 命令查看 /bin/sh 文件,发现 /bin/sh 是一个指向了 /bin/dash 的软连接,那是不是把它指向 /bin/bash 就行了呢?

使用 ln 命令将 /bin/sh 指向了 /bin/bash,重启容器,使用 gdb 调试应用程序并退出后发现没有僵尸进程了。

问题是解决了,那这个问题是怎么导致的呢?

问题分析

使用 ps 命令查看了下进程的父子关系。

在我的容器中,由于用不习惯默认的 /bin/dash,进入终端后我就直接切换了 /bin/bash 了,也就是说 gdb 是由 /bin/bash 启动的,退出时却由 /bin/dash 进程收养,因此出现了僵尸进程。

在leader的容器中,gdb 由 /bin/bash 启动,退出时也由 /bin/bash 进程收养,没有出现僵尸进程。

那我的容器和leader的容器进程号为 1 的进程一个是 /bin/bash 另一个却是 /bin/dash 是怎么导致的呢?

leader的容器基于基础镜像制作,基础镜像由 Dockerfile 生成,Dockerfile 指定了启动进程为 /bin/bash。

我的容器由 leader 通过 docker export 命令导出,由于只有镜像的文件系统,启动进程为 Ubuntu 系统默认的 /bin/sh(/bin/dash)。

那leader为何只使用 docker export 导出了镜像的文件系统,而没有使用 docker commit 之后再 docker save 导出完成的镜像文件呢?
因为leader的开发环境之前的旧版本中安装了一些现在用不上的工具,通过 docker export 导出镜像的文件系统比导出完整的镜像文件占用的空间要小得多。

并未继续深究为何由 /bin/bash 进程启动的进程退出后由 /bin/dash 进程收养就会出现僵尸进程的问题,感兴趣的可以自行去研究下底层机制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值