Supervisor is a client/server system that allows its users to monitor and control a number of processes on UNIX-like operating systems.
Supervisor是一个在类UNIX系统上,监控控制大量进程的客户端/服务端系统。其主要功能包括程序自动启动、程序奔溃后自动重启,指定进程数目等等。本文是Supervisor安装、配置和使用的简单教程。
安装软件
在Ubuntu系统上,我们使用apt安装supervisor,命令如下:
1 | $ sudo apt install supervisor |
安装成功之后,systemd依据随软件一起安装的supervisor.service,自动启动supervisord,如下图所示:
使用示例
成功安装以及正确启动supervisor之后,我们使用一个简单的例子来介绍其使用方法:使用python3内置的http.server为例,让supervisor来负责http.server的启动、停止、重启以及随机启动等操作。
第一步:创建被管理程序的配置文件
首先,我们需要让supervisord知道其待管理程序的基本信息,比如该程序在系统中的标识、启动方法、停止方法、进程数量等属性,所以需要给被管理程序做个配置文件,然后通知supervisord读取该配置文件,supervisord依据该配置文件对程序在系统内部进行进一步的管理。
我们在 /etc/supervisor/conf.d 目录下创建配置文件,文件名称自定义即可,一般我保持配置文件名字和服务名字一致,如本例为httpserver.conf。然后在配置文件中输入以下内容:
1 | [program:httpserver] |
新建配置文件之后,其成品如下图所示:
第二步:通知supervisord加载配置文件,并启动httpserver
使用如下命令加载配置文件:
1 | $ sudo supervisorctl update |
实际操作过程,如下图所示:
从上图我们可以看出,当supervisord重新加载配置文件之后,httpserver被系统成功启动。
好了,我们目前已经可以确认supervisord会帮我们启动程序了。下面我们再做一些其他的测试:
A.程序崩溃(我们使用kill -9模拟)之后,系统自动重启httpserver
B.我们主动停止httpserver的方法
主动停止使用如下命令:
1 | $ sudo supervisorctl stop httpserver |
其执行过程如下图所示:
C.我们主动停止httpserver后,手工重启的方法
主动停止使用如下命令:
1 | $ sudo supervisorctl start httpserver |
其执行过程如下图所示:
D.被管理程序配置文件修改之后,重新加载的方法
修改被管理程序配置文件,改变了该程序运行的一些属性,比如当前httpserver监听在20080端口上,我们修改配置文件让其监听在20081端口上。如果仅使用sudo supervisorctl restart httpserver
,你会发现重启之后的程序依然监听在20080端口上,也就是说在supervisord不重启或者不通知supervisord重新加载配置文件的情况下,使用restart命令是不会改变已在supervisord内存中的属性。
所以,修改配置文件之后要么让supervisord重启,要么让supervisord重新配置文件(重新加载配置文件,发现与内存属性不一致时,会重启程序)。
主动加载配置文件,使用如下命令:
1 | $ sudo supervisorctl update |
其执行过程如下图所示:
E.停止supervisord服务,以及重新启动
停止supervisord服务,使用如下命令:
1 | $ sudo supervisorctl shutdown |
supervisord服务停止之后,使用如下命令重新启动:
1 | $ sudo systemctl start supervisor.service |
其执行过程如下图所示:
通过上述操作过程我们可知:
- 执行 sudo supervisorctl shutdown 之后,会将当前其所管理的所有程序都停止掉
- 执行 sudo systemctl start supervisor.service 之后,会将当前其所管理的所有可随supervisord重启而重启的程序都重启
supervisorctl命令介绍
使用 supervisorctl help
命令获取 supervisorctl 支持的命令列表,如下图所示:
0x00:查看进程运行状态
1 | $ sudo supervisorctl status <arguments> |
1
2
3
4
5
6mancode@manos:~$ supervisorctl help status
status <name> Get status for a single process
status <gname>:* Get status for all processes in a group
status <name> <name> Get status for multiple named processes
status Get all process status info
mancode@manos:~$
0x01:启动进程
1 | $ sudo supervisorctl start <arguments> |
1
2
3
4
5
6mancode@manos:~$ supervisorctl help start
start <name> Start a process
start <gname>:* Start all processes in a group
start <name> <name> Start multiple processes or groups
start all Start all processes
mancode@manos:~$
0x02:停止进程
1 | $ sudo supervisorctl stop <arguments> |
1
2
3
4
5
6mancode@manos:~$ supervisorctl help stop
stop <name> Stop a process
stop <gname>:* Stop all processes in a group
stop <name> <name> Stop multiple processes or groups
stop all Stop all processes
mancode@manos:~$
0x03:重启进程
1 | $ sudo supervisorctl restart <arguments> |
1
2
3
4
5
6
7mancode@manos:~$ supervisorctl help restart
restart <name> Restart a process
restart <gname>:* Restart all processes in a group
restart <name> <name> Restart multiple processes or groups
restart all Restart all processes
Note: restart does not reread config files. For that, see reread and update.
mancode@manos:~$
注意:Note: restart does not reread config files. For that, see reread and update.
0x04:重新加载配置文件
1 | $ sudo supervisorctl update <arguments> |
1
2
3
4
5mancode@manos:~$ supervisorctl help update
update Reload config and add/remove as necessary, and will restart affected programs
update all Reload config and add/remove as necessary, and will restart affected programs
update <gname> [...] Update specific groups
mancode@manos:~$
注意:
- 使用update命令,系统会重新读取配置文件。
- 然后第一会重启配置文件变化过的原已经运行的程序,未变化的子进程保持原样不受影响。
- 然后第二会启动新增加的子进程服务程序。
0x05:重新加载所有配置文件
1 | $ sudo supervisorctl realod |
1
2
3mancode@manos:~$ supervisorctl help reload
reload Restart the remote supervisord.
mancode@manos:~$
注意:
- 该命令重新加载所有配置文件
- 该命令不会重启supervisord主进程
- 该命令重启所有子进程
0x06:关闭supervisord
1 | $ sudo supervisorctl shutdown |
1
2
3mancode@manos:~$ supervisorctl help shutdown
shutdown Shut the remote supervisord down.
mancode@manos:~$
0x07:清除日志
1 | $ sudo supervisorctl clear |
1
2
3
4
5mancode@manos:~$ supervisorctl help clear
clear <name> Clear a process’s log files.
clear <name> <name> Clear multiple process’ log files
clear all Clear all process’ log files
mancode@manos:~$
supervisor管理平台
supervisor自带一个可视化的管理平台,我们可以通过浏览器访问管理平台,然后通过该管理平台查看进程状态、启动、停止后者重启进程。我们使用apt安装supervisor,默认配置文件中没有打开该项功能。我们在配置文件 /etc/supervisor/supervisord.conf 查找 inet_http_server 配置域,如果没有该配置域,我们在配置文件中添加如下内容:
1
2
3
4[inet_http_server]
port=0.0.0.0:9001
username=admin
password=123
- port 管理平台监听的地址和端口,可以自定义
- username 登录管理平台的账号,可以自定义名称
- password 登录管理平台的密码,可以自定义名称
修改的配置文件如下图所示:
修改配置文件之后,我们重新启动supervisord,使用如下命令:
1 | $ sudo supervisorctl reload |
supervisord重启之后,我们在其他主机的浏览器上访问该管理平台,如下图所示:
supervisor不能管理守护进程
我们要特别注意一点,supervisor不能去管理那些后台守护进程!(目前我还未发现解决方法)
关于这种情况,我们编写一个可以进入后台守护进程模式的服务,来进行验证。测试代码文件如下所示:
1 |
|
使用如下命令编译服务:
1 | $ cc -o sptest sptest.c |
被管理程序的配置文件,如下所示(其中启动服务所用-d选项表示进入后台守护进程模式):
1 | [program:sptest] |
如上工作准备完毕之后,我们使用 sudo supervisorctl update
通知supervisord重新加载配置文件,然后稍后我们查看下服务状态:
上图显示,我们的后台守护进程sptest服务,因为退出太快而被设置为了FATAL状态。我们再看下此时 supervisord 的日志:
看启动日志,我们也能看到supervisor尝试4次启动sptest,但守护进程的特点就是服务启动后会马上fork第二个进程,而第一个进程退出,但supervisor的机制就是监控第一个进程号是否存在来判断服务启动成功与否,以及后续依据第一个进程号来判断进程是否崩溃。可见对于守护进程,目前supervisor还掌控不了,至少我没有找到解决方法。
那这个时候,服务到底启动没有?我们ps下进程看看:
显而易见,服务已经启动,而且被启动了4个实例。
这种情况,我觉得也有办法解决:
- 假如子进程不是强制进入守护模式,supervisor本来就是以后台进程的方式启动的子进程,那么子进程启动时不要指定使用自己的守护进程模式,让supervisor来负责后台守护即可。
- 期待官方的改进,比如上述的测试实例,程序内部写了pidfile,那supervisor的配置文件中,加个pidfile的配置项。
然后supervisor去监控该pidfile中的pid,就能解决上述问题。