扩展阅读:理解Docker容器的进程管理

最顶层的是系统初始化时创建的root namespace(根名空间),再创建的新PID namespace就称之为child namespace(子名空间),而原先的PID名空间就是新创建的PID名空间的parent namespace(父名空间)。

在Docker中,每个Container都是Docker Daemon的子进程,每个Container进程缺省都具有不同的PID名空间。

当创建一个Docker容器的时候,就会新建一个PID名空间。容器启动进程在该名空间内PID为1。当PID1进程结束之后,Docker会销毁对应的PID名空间,并向容器内所有其它的子进程发送SIGKILL。

问题分析

一个docker容器同时只能管理一个进程,这个进程退出后,容器也就退出了,当然一个容器里可以同时运行多个进程。当容器启动完后执行某脚本后,该进程结束了,其他进程也结束了,所以该容器自动退出了,解决方案:我们可以让该脚本一直运行不停止。

解决方案

在脚本最后一行添加tail -f /dev/null,这个命令永远完成不了,所以该脚本一直不会执行完,所以该容器永远不会退出。


原文:https://blog.csdn.net/yhf_szb/article/details/52074360

有时候我们在运行服务端系统的时候会遇到这样的问题,希望一个进程能常驻,而不是随着会话的结束而结束,常见如Mysql、Apache等web服务都有类似的需求。

这种不会随着会话退出而自己结束的进程,可以叫做守护进程(Daemon),而像Mysql、Apache这类程序,已经很贴心的提供了守护进程的配置,甚至是默认就是已守护进程的形式工作的。

其实守护进程还有更严谨的定义,这里就不展开了

但有时候我们如果需要运行一个自己的程序,或者某个不支持守护进程的程序时,就需要做些额外的动作让这个进程不会随着会话退出而退出

所以经常看到类似mysqld、httpd啥的,这里的d就是Daemon的意思

贴心点的如swoole server,在配置中补上一个daemon配置即可,麻烦点如beego的server,可以用类似这样的命令:

nohup path/XXX &

严格来说,这样启动的并不是守护进程,不过从结果来说,也可以说它已经是“守护进程”了

总所周知,linux系统中有一个很重要的信号机制,进程可以通过一系列信号进行通讯,例如说,经常为了关闭一个进程使用的

kill -TERM <#pid#>

而用户结束当前会话的时候,会向当前会话的子进程发送一个HUP信号,一般情况下,当前会话的子进程收到HUP信号以后就会退出自己。

也就是说对于交互进程,kill -hup <#pid#>也可以起到退出进程的作用。

看到这里,相信nohup的意思就很明确了,“No HUP”,使用了这个命令以后,启动的进程将忽略HUP信号;

nohup之后还可以配合其他命令重定向输出等,这里就不展开啦

也就是说,因为忽略了HUP的信号,当前会话结束以后,该进程不会自动退出,而是被系统主进程收养(pid = 1),也就产生了形如守护进程的效果。

而&表示将当前进程放入后台执行。

利用nohup命令,我们可以很方便的根据自己的需要启动守护进程,以达到我们的目的,例如对外提供web服务。

简单粗暴好用,再好不过了


如果说nohup命令是用户在使用时根据自己需要实现的守护进程,有些时候作为工具的制造者的攻城狮也可以让程序运行时自动蜕变成守护进程的方法

适度的封装是为了降低使用者的门槛

比较传统的守护进程程序实现思路如下:

  1. 创建子进程,父进程退出
  2. 在子进程中创建新会话

beego的graceful实现就是fork出子进程以后,子进程反手就把把父进程关闭了 ———— 总觉得是一出麦克白…

由于父进程是由会话终端启动的,此时父进程就隶属于会话进程,如果此时会话退出,父进程也会由于收到hup信号而退出

其实父进程只是个壳,子进程才是真正处理业务的进程,有点像鲧和禹的传说

但如果父进程主动退出以后,子进程就变成了孤儿进程,而善良的Linux系统进程(pid = 1)就会收养孤儿进程,这个时候子进程就已经从组织上脱离会话进程了

独立成人总是长大的一部分,但童年的经历也是人生的一部分

子进程仍然会继承父进程与会话有关的会话期的信息,此时需要让子进程自己创立自己的会话,并担任会话组的组长

就像成人仪式一样,宣布正式脱离原会话的控制、原进程组的控制、原控制终端的控制

具体实现上,不同的语言有不同的写法,所以这里只简单介绍一下原理咯~

一般来说就是fork和 … 你猜?


守护 ~ 守护进程 ~ 的进程

守护进程虽然不会因为会话的退出而退出,却有可能因为各式各样的原因出现异常而崩溃。

一些web服务往往要求有比较高的可用性,服务进程崩溃以后,用户往往看到的就是404了

但大多时候都是稳定的服务,偶发性的崩溃却很难及时的通知到管理员

毕竟很多程序不是自己写的,要在程序内部做点监听啥的还真不容易(也没必要)

而且很多时候,只要重启一下服务即可,如果有一个方法可以监视着服务进程,如果发生了异常的退出则自动重启服务进程,就好了

例如丶运维攻城宅可以7*24小时每隔2秒刷新一下网页,看看有没有404 …

显然这种工具是有的,Supervisor就是其中一个。

Supervisor

Supervisor是一个用Python写的进程管控工具,简单地说,它主要解决了两个问题:

  1. 管:进程的启动和守护进程化
  2. 控:监控进程是否异常退出,根据需要重启进程。

当然,Supervisor还可以做得更多…

关于Supervisor的安装说明网上很多,这里就不一一细说了,我们还是来聊聊Supervisor可以怎么管及怎么控你需要的进程。

进程配置文件简析

一个简单的Supervisor进程配置文件可能是这样的:

[program:nginx]
command=/usr/sbin/nginx ;the program (relative uses PATH, can take args)

没错,就这么简单,你只需要把启动进程的命令写进去就可以了,剩下的事情,Supervisor会自动帮你搞定。

Sometimes, simple is the best

这个配置文件中有两个关键属性,第一个是第一行中的“nginx”,这个参数表明了对于Supervisor来说,这个进程应该怎么称呼

毕竟每次运行的时候,进程号都是新分配的,用进程号显然极不方便

第二个属性显然是command,这里就跟你在shell中调用一样,把你想启动的程序的命令写进去吧,可以带参数,也可以不带。

同样,更多的配置略

Supervisord和Supervisorctl

安装完Supervisor以后,系统中一般会找到两个工具(程序),一个是supervisord,另一个是supervisorctl,前者是主要的工作程序,后者则是一个管理工具,两者的关系类似apache和apachectl

事实上,ctl的基本工作就是把人比较好理解的命令转译给正在工作的d,就像高级语言,最终会被转成cpu指令执行一样

首先使用superviaord启动supervisor的主进程,然后通过supervisorctl向主进程发送一系列命令,让它听你的命令工作。

木有错,这里的d就是前文说的Daemon的意思

首先,supervisord启动后,其自身就会蜕变成一个守护进程,然后,它会根据用户的配置文件,根据用户启动配置启动用户需要的进程,而用户配置的进程就变成了supervisord的子进程

这里可不需要nohup ~

如果子进程发生了什么意外导致退出,supervisord进程会收到子进程挂掉的消息,然后重新启动子进程

默认情况下,supervisor的意外表示进程的 exit_code != 0 || exit_code != 2

这样就是守护-守护进程-的进程,由supervisor替管理员管理服务进程的生命周期

常用的命令如supervisorctl start|reload|stop|update这里就不细说咯

意外,总是如期而至

事实上,用supervisor启动守护进程,某种程度上有点像nohup的方法,把自身非守护进程的进程当作守护进程再运行,所以如果某个程序本身就是默认以守护进程的方式运行的,就会出问题

还记得前文中介绍的自身守护进程化的方式么?

我们假设用supervisor启动了默认的nginx服务,刚启动的一瞬间,进程的结构可以简单看作是这样的:

systemd pid = 1
\- supervisord pid = 1234
\= nginx pid = 5678

但nginx默认是自身守护进程化的,也就是说,这个时候pid=5678的进程是父进程,此时他会根据自己的逻辑fork出子进程(假设pid = 8765)用于处理业务:

systemd pid = 1
\- supervisord pid = 1234
\= nginx pid = 5678
\- nginx pid = 8765

然后,父进程(pid = 5678)退出,子进程(pid = 8765)被主进程(pid = 1)收养:

systemd pid = 1
|
\- supervisord pid = 1234
|
\- nginx pid = 8765

这时,问题来了,supervisor发现自己的小弟nginx(pid=5678)退出了,真正的业务进程()pid = 8765)并不是组织(super联萌)的人,那么也就是说,nginx本意是为了脱离会话的控制而华为守护进程的行为,也导致了它无法被supervisor守护

毕竟,人是社会性动物,人设计的程序、系统、制度,或多或少都会体现这一点

那么解决的方法是什么呢?也很简单,告诉nginx不要自己蜕变成守护进程即可:

# 编辑nginx的配置文件
daemon off;

此时,nginx就不会主动的守护自身,而是把这个权利让渡给了supervisor,由supervisor守护自己

是不是有点公民权利让渡的味道(^^__^^)

除了supervisor,常用的apahce也有类似的问题,解决方式如下:

;supervisor的apache2配置中
command = PathToApache/apache2ctl -DFOREGROUND;

后记

关于守护进程,从早年在不知情的情况下用apahce、mysql,到在学习swoole的时候第一次知道守护进程的概念,从自己写的process守护,到使用supervisor,一路走来,今天写这篇稿的时候忽然有点唏嘘。

【转】守护进程二三事与Supervisor的更多相关文章

  1. Python—守护进程管理工具(Supervisor)

    一.前言简介 1.Supervisor 是一个 Python 开发的 client/server 系统,可以管理和监控类 UNIX 操作系统上面的进程.可以很方便的用来启动.重启.关闭进程(不仅仅是 ...

  2. Linux 守护进程二(激活守护进程)

    //守护进程--读文件 #include <stdio.h> #include <stdlib.h> #include <string.h> #include &l ...

  3. 实用,Windows后台守护进程iNeuDaemon发布。Linux操作系统下使用使用supervisor

    目       录 1.      概述... 1 2.      iNeuDaemon部署... 2 3.      iNeuDaemon配置监控服务项... 3 4.      应用效果... 3 ...

  4. 20181229(守护进程,互斥锁,IPC,生产者和消费者模型)

    一.守护进程 守护进程:一个进程B守护另一个进程A,当被守护的进程A结束,进程B也就结束了.(不一定同生,但会同死) 两个特点: ①守护进程会在主进程代码执行结束后就终止 ②守护进程内无法再开启子进程 ...

  5. asp.net core2.0 部署centos7/linux系统 --守护进程supervisor(二)

    原文:asp.net core2.0 部署centos7/linux系统 --守护进程supervisor(二) 续上一篇文章:asp.net core2.0 部署centos7/linux系统 -- ...

  6. [Linux] PHP程序员玩转Linux系列-使用supervisor实现守护进程

    1.PHP程序员玩转Linux系列-怎么安装使用CentOS 2.PHP程序员玩转Linux系列-lnmp环境的搭建 3.PHP程序员玩转Linux系列-搭建FTP代码开发环境 4.PHP程序员玩转L ...

  7. Centos7 使用 Supervisor 守护进程 Celery

    一.Supervisor 安装(centos7 还有另一个进程守护命令 Systemd ) Centos 7 安装 Supervisord 二.Supervisor 守护进程 Centos7 使用 S ...

  8. ASP.NET Core教程:使用Supervisor做ASP.NET Core应用程序守护进程

    一.前言 在上一篇文章中,我们讲解了如何在Linux服务器上面部署ASP.NET Core应用程序,并且使用Nginx作为反向代理.我们在Linux服务器上面,是通过ASP.NET Core自宿主的方 ...

  9. Linux Supervisor 守护进程基本配置

    supervisor:C/S架构的进程控制系统,可使用户在类UNIX系统中监控.管理进程.常用于管理与某个用户或项目相关的进程. 组成部分supervisord:服务守护进程supervisorctl ...

随机推荐

  1. Beego 学习比较8:SQL语句

    SQL语句 1>     常用的SQL语句 1->新增  insert into 表名(字段A,字段B,…) Values(字段A值,字段B值,…) 2->更新  update 表名 ...

  2. Python操作SQLite/MySQL/LMDB

    1.概述 1.1前言 最近在存储字模图像集的时候,需要学习LMDB,趁此机会复习了SQLite和MySQL的使用,一起整理在此. 1.2环境 使用win7,Python 3.5.2. 2.SQLite ...

  3. JavaScript 之 页面加载事件

    一.onload 加载事件 onload 是 window 对象的一个事件,也可以省略 window 直接使用. 常用方式: <head><script> windown.on ...

  4. PHP的垃圾回收机制之引用计数

    1,介绍 php的垃圾回收机制(GC)是在PHP5之后出现的,而在PHP5.3版本之前使用的都是“引用计数”的方式.实现引用计数的实质就是在每个内存对象中都有一个计数器,当内存对象被变量引用时,计数器 ...

  5. prometheus学习系列三:node_exporter安装部署

    node_exporter简介 node_exporter安装部署 [root@node00 ~]# cd /usr/src/ [root@node00 src]# wget https://gith ...

  6. AM335X UBOOT(以UART为例分析UBOOT主要流程)

    UBOOT2016.05 UART初始化及设置 SPL阶段 第一部分C函数 |- s_init //(arch/arm/cpu/armv7/am33xx/board.c) |- set_uart_mu ...

  7. python之提升程序性能的解决方案

    Python在性能方面不卓越,但是使用一些小技巧,可以提高Python程序的性能,避免不必要的资源浪费. 1. 使用局部变量 尽可能使用局部变量替代全局变量,可以是程序易于维护并且有助于提高性能节约成 ...

  8. excel 大文件解析原理实现

    问题 目前的excel 不像之前的excel了可以支持的数据量更大,可以支持支持1048576行,16384列. 之前使用poi读取,直接报错,使用excel 事件的方式读取,还有不少的bug,关键是 ...

  9. 如何学习numpy

    可以通过官方中文文档 NumPy 中文文档

  10. TCP滑动窗口(发送窗口和接受窗口)

    TCP窗口机制 TCP header中有一个Window Size字段,它其实是指接收端的窗口,即接收窗口.用来告知发送端自己所能接收的数据量,从而达到一部分流控的目的. 其实TCP在整个发送过程中, ...