搬砖程序员带你飞

Supervisor 的使用和进阶 (1)

路漫漫其修远兮,吾将上下而求索。

字数统计: 1.9k阅读时长: 7 min
2020/04/03 Share

再也不怕进程意外退出。

supervisor 是Python 开发的一套通用的进程管理程序,用于管理类Unix系统上的应用程序。
可以实现对服务的命令行、WEB、XML等方式的管理,实现对服务的启动、重启、关闭等操作。

supervisor 可以干什么

  • 管理进程,对进程进行开启、关闭、重启等服务;
  • 守护管理的进程。当进程关闭后,可以自动重启;
  • 管理一组进程,一组进程同时启动,关闭,重启等服务;
  • 提供事件管理,用于管理的进程触发的事件进行报警的功能(supervisor 3.0 引入);
  • 提供了对监听同一个unix socket 文件的cgi服务的管理;
  • 提供web服务做服务管理;
  • 提供XMLPRC服务做二次开发;

服务安装

以生产环境使用较多的CentOS 为例, 使用yum包管理器即可完成安装,命令如下:

1
yum install supervisor

如何非centos系统,则可以使用Python 强大的包管理器pip来完成安装。

1
pip install supervisor

安装完成后,生成配置文件。supervisor 提供了 echo_supervisord_conf 命令,用于生成supervisord 的配置文件。
如果pip安装,echo_supervisord_conf 会安装在相应pip的目录下。

一般配置文件会保存至/etc/ 目录下,生成方式如下:

1
2
echo_supervisord_conf > /etc/supervisord.conf
mkdir -p /etc/supervisor.d // supervisord 支持include 的方式将多个配置放置不同文件中, 需要配置文件中指定

supervisor 提供了两个命令给用户:
- supervisord supervisor 守护其他服务的进程
- supervisorctl supervisor的命令行工具

最后启动supervisor即可:

1
supervisord -c /etc/supervisord.conf

PS:

如果使用yum管理安装的,可以直接使用systemctl 管理启动和暂停supervisord。

服务的配置

简单介绍两种比较常用的配置。

对简单进程的管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
;[program:theprogramname]
;command=/bin/cat ; 启动命令
;process_name=%(program_name)s ; process_name expr (default %(program_name)s)
;numprocs=1 ; 同一个任务如果需要启动多次,需要配置此项,并配置process_name为类似于 %(program_name)%02d 格式
;directory=/tmp ; 任务执行的当前目录
;umask=022 ; 进程文件权限掩码 (默认创建文件为0644
;priority=999 ; 优先级
;autostart=true ; 是否自动开启。(当supervisord 启动时)
;startsecs=1 ; 程序开启 startsec s内不退出
;startretries=3 ; 最大尝试次数
;autorestart=unexpected ; 是否退出后自动重启 (默认不重启,对于经常意外退出的服务可以开启)
;exitcodes=0 ; 判断是否正常退出码
;stopsignal=QUIT ; 关闭的信号 (默认时TERM, 也就是Ctrl-C)
;stopwaitsecs=10 ; 服务关闭等待事件。若关闭事件超出,则发送 SIGKILL 信号 (也就是 kill -9)
;stopasgroup=false ; 是否为杀死子进程,默认不杀死。(将会出现未纳入管理的孤儿进程)
;killasgroup=false ; 发送SIGKILL 信号的时候,是否杀死子进程
;user=chrism ; 启动的用户
;redirect_stderr=true ; 将进程的标准输出重定向为标准输出
;stdout_logfile=/a/path ; 进程标准输出
;stdout_logfile_maxbytes=1MB ; 之日滚动大小,默认50M
;stdout_logfile_backups=10 ; 日志最多保留个数
;stdout_capture_maxbytes=1MB ; 捕获输出的日志,当事件开启时发送给event_listener (也就是事件监听进程)
;stdout_events_enabled=false ; 对于标准输出的情况是否发送event
;stdout_syslog=false ; 是否发送到syslog
;stderr_logfile=/a/path ; 标准错误输出路径
;stderr_logfile_maxbytes=1MB ; 最大标准错误输出的日志文件大小(默认50M)
;stderr_logfile_backups=10 ; 日志最多保留个数 (10个)
;stderr_capture_maxbytes=1MB ; 捕获标准错误输出的日志,当 stderr_events_enabled 开启时发送给event_listener
;stderr_events_enabled=false ; 对于标准错误输出的情况是否发送event
;stderr_syslog=false ; 是否发送错误输出日志到syslog
;environment=A="1",B="2" ; 子进程的环境变量设置,可用的变量有 `group_name`, `host_node_name`, `process_num`, `program_name`, `here`。

对进程组的管理

除了对单个进程(或者相同的进程)进行控制外,还可以将多个program分组进行控制。

例如有服务 bar,baz, 可以定义进程组:

其他模式

如cgi 服务管理、事件监听,后面做详细讨论。

1
2
3
[group:foo]
programs:bar, baz
priority:999

对group做开启,暂停,则对下面的bar,baz都会生效。使用时可以用如下命令:

1
supervisorctl [start | stop | restart | status] foo:

当然,可以使用通过 foo:bar 管理bar服务

常见命令行

supervisorctl 是supervisor 提供的配套命令行工作,用于对supervisor做命令行控制。

本地服务的启动和暂停

本地服务的启动暂停,使用的是 unix socket的方式对supervosrd 发送命令的。因此,使用本机操作命令,必须指定unix socket 的路径。
配置如下:

1
2
[supervisorctl]
serverurl=unix:///var/tmp/supervisor.sock

命令行操作服务的启动和暂停

1
supervisorctl [start | stop | restart | status ] jobname

远程的启动和暂停

如果开启了远程操作的端口,也可以通过命令行方式操作远程服务。

1
supervisorctl -s hostname:9001 [-u user] [ -p password] [ start | stop | restart | status ] jobname

supervisor 配置更新和修改

  • supervisor 服务配置更新, 并对修改的服务做相应操作
1
supervisorctl update
  • supervisor 服务配置更新,并重启所有服务。
1
supervisorctl reload

其他操作可以参考supervisor官方文档

Web 服务

supervisor 提供了简约而不简单的操作见面,可以在浏览器端对服务做远程控制。

web 服务需要做如下配置,开启服务监听

1
2
3
4
[inet_http_server] 
port=*:9001
username= test
password=testpass ; 可以不需要账号密码

以下为操作界面:
supervisor web 服务

web 服务除了可以对服务做启动暂停等操作外,还可以远程查看应用的日志,监控服务的log 是否正常。这在普通的web 服务中还是比较常用的。

二次开发

supervisor 提供了XMLRPC接口用于使用它的人可以二次开发利用。

例如,可以通过远程访问 supervisor 服务控制应用服务的启动、暂停。获取应用服务当前的服务状态等。因此可以通过supervisor 的xmlrpc 监控对supervisor 管理的服务做多服务远程监控

使用xmlrpc时,需要设置inet_http_server, 用于监听rpc和web服务的端口。(建议仅监听内网IP,并设置相应密码)
对于PHP服务,我做了简单的封装,可以从Github中获取:github.com/lpflpf/supervisor_phpctl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

function monitor($host, $port, $jobname){
$server = new Supervisord($host, $port);

$state = $server->getState();

switch ($state['statename']){
case 'RUNNING': // 服务正常
break;
case 'RESTARTING': // 服务重启
break;
case 'SHUTDOWN': // 服务关闭
break;
case 'FATAL': // 服务出现错误退出
//alarm();
return;
}
}

supervisor 原理

  • supervisord 管理的任务进程都是supervisord 的子进程, 通过 fork/exec 方式启动子进程。
  • supervisord 杀死子进程,其实就是发送给子进程一个中断信号(这个信号可以自定义, 参数为stopsignal, 默认为TERM信号)

其他需要强调的点

  • supervisor 不会随着系统的重启而启动,因此那些依赖supervisor的服务也不会随着系统重启而启动。(别问我是怎么知道的)
    解决办法也简单。只需要将supervisor 开机启动就行。不同版本操作系统不太一样。

centos 可以用如下方法:

1
2
chkconfig --add supervisord
chkconfig supervisord on
  • supervisor 管理的进程可能存在多种状态,在做服务监控时需要注意, 如下为进程状态转移图:

supervisor进程转移图

需要注意backoff 状态,当服务不断进行快速关闭重启,则会进入baockoff 状态。这种状态一般也是有问题的。

  • 对于进程组的操作

    • 如果操作进程组中的某个进程,jobname 使用自定义的process_name。
    • 如果操作进程组中的所有进程,使用process_name:* 即可

其他类似服务

原文作者:lpflpf

原文链接:http://blog.lpflpf.cn/passages/supervisor1/

发表日期:2020-04-03 16:30:42

更新日期:2020-04-07 09:30:10

版权声明:本文采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可

CATALOG
  1. 1. supervisor 可以干什么
  2. 2. 服务安装
  3. 3. 服务的配置
    1. 3.1. 对简单进程的管理
    2. 3.2. 对进程组的管理
    3. 3.3. 其他模式
  4. 4. 常见命令行
    1. 4.1. 本地服务的启动和暂停
    2. 4.2. 远程的启动和暂停
    3. 4.3. supervisor 配置更新和修改
  5. 5. Web 服务
  6. 6. 二次开发
  7. 7. supervisor 原理
  8. 8. 其他需要强调的点
  9. 9. 其他类似服务