• GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。

一、发现问题

小玲是一名数据库测试人员,这一天她尝试在docker环境中部署GreatDB集群,结果在对greatsqld进程进行kill操作后,意外发现greatsqld进程变成了僵尸进程(如下图所示)。

由于小玲成为测试人员的时间较短,她没有遇见过这种情况,所以无法第一时间判断这个现象,是她的操作失误导致的合理现象,还是一个新发现的bug。

于是她进行了以下尝试:

  • 1.在物理机上重复上述操作,并没有出现僵尸进程。
  • 2.在docker内,对MySQL的mysqld进程进行相同操作,出现了僵尸进程。

通过这样的尝试,小玲初步判断出docker环境才是产生僵尸进程的根源,但具体是什么原因,又该如何避免,还需要小玲的进一步探索。

二、僵尸进程简介

首先需要搞清楚的是:

  • 僵尸进程是什么?

  • 僵尸进程又是如何形成的?

以下定义内容和解决办法来自维基百科。

僵尸进程:在类UNIX系统中,僵尸进程是指完成执行(通过exit系统调用,或运行时发生致命错误或收到终止信号所致),但在操作系统的进程表中仍然存在其进程控制块(PCB),处于"终止状态"的进程。僵尸进程不能被杀死,因为它们已经死亡,只等待它们的父进程回收它们。

通过这样的概念,和其他一些相关材料,小玲了解了僵尸进程的出现,问题多半是出现僵尸进程的父进程上。

这时,小玲看到了一个比较简单粗暴的解决办法,就是直接将僵尸进程的父进程杀死。她立刻去实践了一番,可惜她又失败了。

在docker中,她kill产生的僵尸进程的父进程PID是1,而1这个进程在docker内部是kill不掉的;如果在docker外部的物理机找到1的对应进程进行kill,则会将整个容器杀死。

三、孤儿进程的出现

小玲并不气馁,她继续通过搜索引擎进行探索学习,很快她就了解到更多的概念。

当进程的父进程id变为1的时候,这个进程也有了专门定义的称谓,叫做孤儿进程。

孤儿进程:父进程结束后仍在运行的子进程。

没有了父进程总要有人“照顾”它。

在类UNIX操作系统中,为避免孤儿进程退出时无法释放所占用的资源而僵死,任何孤儿进程产生时都会立即被系统进程init或systemd自动接收为子进程,这一过程也被称为“收养”。在此需注意,虽然事实上该进程已有init作为其父进程,但由于创建该进程的进程已不存在,所以仍应称之为“孤儿进程”。

根据上面的解释,又引出来一个概念,init 进程。我们也来看下它的定义。

init进程:是 Unix 和 类Unix 系统中用来产生其它所有进程的程序。它以守护进程的方式存在,其进程号为1。init进程是特殊的:它不获得它不想处理的信号,因此它可以忽略SIGKILL。

这里又有个新概念,SIGKILL信号。

一般我们kill进程是发信号给进程,然后被进程捕获之后执行对应操作。主要需要了解的信号有下面3种。都是来终止进程使用的。

四、整理现象发生的过程

小玲已经清楚这个现象跟GreatDB和MySQL都没有关系了,于是使用sleep命令继续尝试。

进入容器,执行命令。此时子进程PID是61,父进程PID是44,父进程是bash。

退出容器,再进入容器。PID是44的bash进程因为退出容器的操作被杀死,子进程61就被init收养了,父进程的PID就变成了1。

杀掉这个进程61,然后查看这个进程状态,发现它已经成为一个僵尸进程。

到这里,小玲就已经很接近问题的真相了:docker容器在默认的参数配置下,其init进程并没有处理孤儿进程的能力。

对于这个问题,docker的开发者们已经考虑到了。

五、如何处理docker中的僵尸进程

有两个解决办法可以让docker的init进程能够处理孤儿进程。

1.启动docker容器时,指定init进程为bash,由bash进程对孤儿进程的资源进行回收。

2.增加专门的 init 进程,比如 tini。

我们可以去docker官方文档找到答案:

The container’s main process is responsible for managing all processes that it starts.In some cases, the main process isn’t well-designed, and doesn’t handle “reaping” (stopping) child processes gracefully when the container exits.If your process falls into this category, you can use the --init option when you run the container.The --init flag inserts a tiny init-process into the container as the main process, and handles reaping of all processes when the container exits.Handling such processes this way is superior to using a full-fledged init process such as sysvinit, upstart, or systemd to handle process lifecycle within your container.

根据文档建议,可以在启动容器时候加上 --init 参数,开始使用tini。这样会有一个tiny的进程来负责进程"收养"之后的处理工作。

接下来我们分别对两种方法进行验证。

5.1 bash 处理

我们尝试将启动容器的命令指定为bash来启动一个容器test01,来看下这个容器会不会出现文章开头的问题。

启动容器,指定命令为bash。这个镜像基于CentOS 7的镜像,装了一些常用的包。

进入test01,确认id为1的进程。

执行sleep 700s &,然后查看父进程id为16,子进程id为33。

退出,重新登录容器test01,查看进程33的父进程,已经被init进程“领养”。

kill 进程33。然后check进程33。发现33没有成为僵尸,已经彻底被终止了。

从上面步骤来看,指定启动命令为bash确实可以解决我们遇到的问题。

5.2 tini 处理

再来试下tini,它是使用C语言写的一个tiny级的init进程,github对此有详细的介绍。

这是一个相当轻量级的init系统,相比较传统的Upstart、Systemd、SysV init 之类的大型系统使用起来更加的优秀。

现在我们在启动docker容器时时候加上--init参数,来看下效果。

加上init参数,启动容器test02,启动命令使用tail -f /dev/null,然后登录查看进程情况。

登录test02,执行sleep 700s &。查看父子进程id。

退出登录。

再次登录之后,查看进程的父进程id。

kill进程,检查进程是否彻底终止。已经看到没有僵尸进程。

六、总结

在使用tail -f /dev/null作为docker容器的init进程时,如果不加上--init参数,就会因为init进程没有处理孤儿进程的能力,而导致僵尸进程的出现。

在这种情况下,我们可以将tail -f /dev/null替换成bash,或是加上--init来解决这个问题。

文章推荐:

GreatSQL MGR FAQ https://mp.weixin.qq.com/s/J6wkUpGXw3YkyEUJXiZ9xA

万答#12,MGR整个集群挂掉后,如何才能自动选主,不用手动干预 https://mp.weixin.qq.com/s/07o1poO44zwQIvaJNKEoPA

『2021数据技术嘉年华·ON LINE』:《MySQL高可用架构演进及实践》 https://mp.weixin.qq.com/s/u7k99y6i7riq7ScYs7ySnA

一条sql语句慢在哪之抓包分析 https://mp.weixin.qq.com/s/AYibbzl860D90rOeyjB6IQ

万答#15,都有哪些情况可能导致MGR服务无法启动 https://mp.weixin.qq.com/s/inSGpd0Q_XIl2Mb-VsvNsA

技术分享 | 为什么MGR一致性模式不推荐AFTER https://mp.weixin.qq.com/s/rNeq479RNsklY1BlfKOsYg

关于 GreatSQL

GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。

Gitee: https://gitee.com/GreatSQL/GreatSQL

GitHub: https://github.com/GreatSQL/GreatSQL

Bilibili: https://space.bilibili.com/1363850082/video

微信&QQ群: 可搜索添加GreatSQL社区助手微信好友,发送验证信息“加群”加入GreatSQL/MGR交流微信群

QQ群:533341697 微信小助手:wanlidbc

本文由博客一文多发平台 OpenWrite 发布!

在docker中出现的僵尸进程怎么处理相关推荐

  1. mysqlfor循环中出错继续_运维大佬教你“打僵尸”——处理Linux系统中大量的僵尸进程(2)...

    接上一篇文章.首先,打开一个终端,登陆到上次的机器中.然后执行下面的命令,重启这个案例: # 先删除上次启动的案例 $ docker rm -f app # 重新运行案例 $ docker run - ...

  2. linux中如何杀死僵尸进程,linux – 如何杀死僵尸进程

    我在前台启动我的程序(一个守护程序),然后我杀了它与杀-9,但我得到一个僵尸剩余,我不能杀死它与杀-9.如何杀死僵尸进程? 如果僵尸是一个死过程(已经杀死),我如何从ps aux的输出中删除它? ro ...

  3. Linux中如何杀掉僵尸进程

    1) 检查当前僵尸进程信息 # ps -ef | grep defunct | grep -v grep | wc -l 175 # top | head -2 top - 15:05:54 up 9 ...

  4. linux怎么杀掉僵尸进程,Linux中如何杀掉僵尸进程

    1) 检查当前僵尸进程信息 # ps -ef | grep defunct | grep -v grep | wc -l 175 # top | head -2 top - 15:05:54 up 9 ...

  5. 【k8s】理解Docker容器的进程管理(PID1进程(容器内kill命令无法杀死)、进程信号处理、僵尸进程)

    文章目录 概述 1. 容器的PID namespace(名空间) 2. 如何指明容器PID1进程 3. 进程信号处理 4. 孤儿进程与僵尸进程管理 5. 进程监控 6. 总结 参考 概述 简介: Do ...

  6. linux mysql 僵尸进程_Linux 系统中僵尸进程

    Linux 系统中僵尸进程和现实中僵尸(虽然我也没见过)类似,虽然已经死了,但是由于没人给它们收尸,还能四处走动.僵尸进程指的是那些虽然已经终止的进程,但仍然保留一些信息,等待其父进程为其收尸. 僵尸 ...

  7. linux java 僵尸进程_Linux 系统中僵尸进程

    Linux 系统中僵尸进程和现实中僵尸(虽然我也没见过)类似,虽然已经死了,但是由于没人给它们收尸,还能四处走动.僵尸进程指的是那些虽然已经终止的进程,但仍然保留一些信息,等待其父进程为其收尸.配图源 ...

  8. 面试中常被问到的(18)父子进程,孤儿进程及僵尸进程

    并发: 单核cpu多任务,宏观同一段时间内表现出同时运行,微观上实际为时间片轮转,同一时刻只能有一个进程占据cpu资源运行,多个任务执行存在先后顺序 并行: 多核cpu多任务,严格物理意义上的同时运行 ...

  9. Unix中的僵尸进程

    现实中的僵尸是一种似死非死的状态--一直在人间四处游走,但是却不能做一些活人能做的事情. 而对于僵尸进程,与这个有些类似,它不能像一般进程那样来执行程序.被调度而占用CPU,但是它却不能消失,因为它还 ...

最新文章

  1. Spring Boot集成Swagger导入YApi@无界编程
  2. Openresty最佳案例 | 第1篇:Nginx介绍
  3. 漫画算法:如何判断链表有环?
  4. 廖雪峰 python_40岁老男人从0开始学python实录(第1天)
  5. Set Up Optimization
  6. Effective C# Item23:避免返回内部类对象的引用
  7. torchtext.data.Field
  8. Cibersort免疫浸润的在线分析及R语言代码实现
  9. maven学习(一)
  10. pdf转html插件~~~pdf2htmlEX安装,配置及使用
  11. Pandas 基础(4) - 读/写 Excel 和 CSV 文件
  12. Java面向对象三大特征
  13. android电视工程模式,智能电视进入工厂/工程模式教程汇总!
  14. 【云原生之Docker实战】使用Docker部署BookStack文档管理系统
  15. 图像搜索引擎 - 原理篇
  16. vue项目 设置scrollTop不起作用(解决方法及原因)
  17. 在抖音全程看世界杯,超高清直播背后的硬实力
  18. 小学老师工资多少一个月_小学教师工资待遇现在怎么样?乡村老教师含泪哭诉!...
  19. day 1 学习MySQL数据库作业 - 创建员工表思考与表之间的关系
  20. 求解SDP问题—使用SeDuMi和YALMIP

热门文章

  1. 【微客云】机器人怎么赚钱运营及功能介绍
  2. DataGridView获取当前选中的行与列的值
  3. php菜单无限极分类
  4. python 使用mechanize进行web网页交互
  5. Stream.flatMap
  6. 什么是自动化测试框架?这就是自动化测试框架。
  7. nginx实现对css,js文件缓存
  8. cadence 怎么拼版_在Allegro中如何拼板
  9. 微信JS-SDK的使用
  10. 华为AC忘记console密码