一直想弄清楚如果在容器跑多进程的话,实际会带来怎么样的坑,在查找相关资料时基本都是在强调跑多进程会出现进程无法被管理的问题,但具体怎么无法管理,会出现怎么样的状况呢?
一般具有进程管理能力的进程需要具备以下的能力,如centos中的systemd
- 如果一个进程的父进程退出了,那么这个 init 进程便会接管这个孤儿进程。
- 如果一个进程的父进程未执行 wait/waitpid 就退出了,init 进程会接管子进程并自动调用 wait 方法,从而保证系统中的僵尸进程可以被移除。
- 传递信号给子进程。
关于僵尸进程
一个进程在调用exit命令结束自己的生命的时候,其实它并没有真正的被销毁,而是留下一个称为僵尸进程(Zombie)的数据结构(系统调用exit,它的作用是使进程退出,但也仅仅限于将一个正常的进程变成一个僵尸进程,并不能将其完全销毁)。在Linux进程的状态中,僵尸进程是非常特殊的一种,它已经放弃了几乎所有内存空间,没有任何可执行代码,也不能被调度,仅仅在进程列表中保留一个位置,记载该进程的退出状态等信息供其他进程收集,除此之外,僵尸进程不再占有任何内存空间。它需要它的父进程来为它收尸,如果他的父进程没有调用wait或waitpid等待子进程结束(当子进程退出的时候,内核会给父进程一个SIGCHLD信号,所以我们可以建立一个捕获SIGCHLD信号的信号处理函数,在函数体中调用wait或waitpid),那么它就一直保持僵尸状态,如果这时父进程结束了,那么init进程自动会接手这个子进程,为它收尸,它还是能被清除的。但是如果父进程是一个循环,不会结束,那么子进程就会一直保持僵尸状态,这就是为什么系统中有时会有很多的僵尸进程。
1、如果容器中的1号进程不具有对僵尸进程的回收能力,那么容器中可能出现大量的僵尸进程,从而占用pid资源。
2、pid为1的进程不响应信号,docker stop或者docker killl能干掉容器是因为信号是在宿主机的视角发给容器中1号进程(未验证)。
3、bash 进程会负责回收僵尸进程,但是bash不转发信号,如果让bash作为1号进程也不合适,因为使用docker stop来停止这样的容器,结果就是docker发送给容器pid为1的进程的SIGTERM信号被忽略,等到stop命令默认的10s graceperiod到了再发送SIGKILL才能