再也不怕进程意外退出。
supervisor 是Python 开发的一套通用的进程管理程序,用于管理类Unix系统上的应用程序。
可以实现对服务的命令行、WEB、XML等方式的管理,实现对服务的启动、重启、关闭等操作。
supervisor 可以干什么
- 管理进程,对进程进行开启、关闭、重启等服务;
- 守护管理的进程。当进程关闭后,可以自动重启;
- 管理一组进程,一组进程同时启动,关闭,重启等服务;
- 提供事件管理,用于管理的进程触发的事件进行报警的功能(supervisor 3.0 引入);
- 提供了对监听同一个unix socket 文件的cgi服务的管理;
- 提供web服务做服务管理;
- 提供XMLPRC服务做二次开发;
服务安装
以生产环境使用较多的CentOS 为例, 使用yum包管理器即可完成安装,命令如下:
如何非centos系统,则可以使用Python 强大的包管理器pip来完成安装。
安装完成后,生成配置文件。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 服务配置更新, 并对修改的服务做相应操作
- supervisor 服务配置更新,并重启所有服务。
其他操作可以参考supervisor官方文档。
Web 服务
supervisor 提供了简约而不简单的操作见面,可以在浏览器端对服务做远程控制。
web 服务需要做如下配置,开启服务监听
1
2
3
4
| [inet_http_server]
port=*:9001
username= test
password=testpass ; 可以不需要账号密码
|
以下为操作界面:
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 管理的进程可能存在多种状态,在做服务监控时需要注意, 如下为进程状态转移图:
需要注意backoff 状态,当服务不断进行快速关闭重启,则会进入baockoff 状态。这种状态一般也是有问题的。
对于进程组的操作
- 如果操作进程组中的某个进程,jobname 使用自定义的process_name。
- 如果操作进程组中的所有进程,使用process_name:* 即可
其他类似服务