当前位置:科技动态 > 关于守护进程和Supervisor的一些事情

关于守护进程和Supervisor的一些事情

  • 发布:2023-09-30 07:18

守护者的梦想

有时我们在运行服务器系统时会遇到这样的问题。我们希望这一进程能够是永久性的,而不是随着会议的结束而结束。常见的Web服务如Mysql和Apache也有类似的需求。 。

这种会话退出时不会自行结束的进程可以称为守护进程。像Mysql和Apache这样的程序都贴心地提供了守护进程的配置,甚至是默认就有的。以守护进程的形式工作。

其实守护进程还有更严格的定义,这里就不多说了

但有时如果我们需要运行自己的程序,或者不支持守护进程的程序,我们需要做一些额外的操作来防止会话退出时进程也退出

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

比较周到的,比如swoole server,在配置中添加一个daemon配置即可。对于比较麻烦的,比如beego的服务器,可以使用类似这样的命令:

nohup 路径/XXX &

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

众所周知,Linux系统中有一个非常重要的信号机制。进程可以通过一系列信号进行通信。例如,

通常用于关闭进程。
 -学期<#pid#>

当用户结束当前会话时,会向当前会话的子进程发送一个HUP信号。正常情况下,当前会话的子进程收到HUP信号后会自行退出。

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

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

nohup之后还可以使用其他命令来重定向输出等,这里就不多说了

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

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

使用nohup命令,我们可以很方便地根据自己的需要启动守护进程来实现我们的目标,比如向外界提供Web服务。

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


如果nohup命令是用户在使用时根据自己的需要实现的守护进程,有时Siege Lion这个工具制作者也可以在程序运行时自动将程序转变成守护进程

适度的包装是为了降低用户的门槛

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

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

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

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

但如果父进程主动退出,子进程就成为孤儿进程,善良的Linux系统进程(pid=1)会收养孤儿进程。此时子进程已经脱离了会话进程。

成为独立的成年人永远是成长的一部分,但童年的经历也是生活的一部分

子进程仍然会继承父进程的会话相关的会话信息。这时候子进程就需要创建自己的session并担任session组的leader

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

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

一般来说,它是叉子......你猜?


守护进程 ~ 守护进程 ~ 进程

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

一些 Web 服务通常需要相对较高的可用性。服务进程崩溃后,用户经常会看到404

但大多数时候都是稳定的服务,只是偶尔崩溃的时候很难及时通知管理员

毕竟很多程序都不是自己写的。在程序内部做一些监控并不容易(也没有必要)

很多时候,只需重新启动服务即可。如果有办法监控服务进程,如果出现异常退出,自动重启服务进程就好了

比如运维攻城房可以7*24小时每2秒刷新一次网页,看看有没有404...

显然有这样的工具,Supervisor就是其中之一。

主管

Supervisor是一个用Python编写的进程管理和控制工具。简单来说,主要解决两个问题:

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

当然,Supervisor可以做更多...

Supervisor的安装说明网上有很多,这里不再赘述。让我们谈谈 Supervisor 如何管理和控制您需要的流程。

流程配置文件简析

一个简单的 Supervisor 进程配置文件可能如下所示:

[程序:nginx]
command=/usr/sbin/nginx ;程序(相对使用PATH,可以带args)

是的,就是这么简单。您只需要编写启动进程的命令,Supervisor 就会自动为您处理剩下的事情。

有时候,简单就是最好的

此配置文件中有两个关键属性。第一个是第一行中的“nginx”。该参数表示Supervisor如何调用该进程

毕竟每次运行都会重新分配进程号。使用进程号显然极其不方便

第二个属性显然是命令。就像在 shell 中调用它一样。编写要启动的程序的命令,带或不带参数。

同样,配置较多略

Supervisord 和 Supervisorctl

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

其实ctl的基本工作就是将人们更容易理解的命令翻译成工作D,就像高级语言一样,最终会转换成CPU指令执行

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

没错,这里的d就是上面提到的Daemon

首先,supervisord启动后,会转变为守护进程。然后,它会根据用户的配置文件和用户启动配置启动用户需要的进程,用户配置的进程就成为supervisord的子进程

这里不需要 nohup ~

如果子进程发生意外情况导致其退出,supervisord进程会收到子进程已死亡的消息,然后重新启动子进程

默认情况下,主管对进程的 exit_code 的意外表示!= 0 ||退出代码!= 2

这是守护进程。主管为管理员管理服务流程的生命周期

supervisorctl start|reload|stop|update等常用命令这里不再详述

意外总是如期而至

其实使用supervisor来启动守护进程有点像nohup的方法。它使用自己的非守护进程作为守护进程,然后运行它,所以如果一个程序本身默认作为守护进程运行的话,就会出现问题

还记得上一篇文章介绍的自我守护的方法吗?

我们假设默认的nginx服务是由supervisor启动的。启动的那一刻,进程的结构可以简单地看成这样:

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

这时候,问题来了。主管发现弟弟nginx(pid=5678)退出了。真正的业务进程(pid=8765)并非来自组织(超联盟),所以换句话来说,nginx的初衷是为了摆脱会话控制,但华为守护进程的行为也让它无法被控制。由主管守护

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

那么解决办法是什么呢?也很简单,只要告诉nginx不要转变成守护进程即可:

#编辑nginx配置文件
守护进程 关闭;

这个时候nginx不会主动保护自己,而是把这个权利交给supervisor,supervisor来保护自己

是不是有点民权移交的味道(^^__^^)

除了supervisor之外,常用的apahce也有类似的问题。解决办法如下:

;supervisor的apache2配置
命令 = PathToApache/apache2ctl -DFOREGROUND;

后记

关于守护进程,从早年不知道的使用apahce和mysql,到学习swoole时第一次了解守护进程的概念,从自己写进程守护进程到使用supervisor,一路走来,今天写这篇文章的时候心情有些难过。

物如其人,一切都结束了

也许成长就是学会接受改变。

相关文章