yield-bytes

沉淀、分享与无限进步

supervisor管理web服务进程

  部分较小的项目例如flask,对内部使用,可无需使用web server,直接用flask自带服务即可完成需求,但考虑到直接使用python app.py启动flask后,运行过程进程可能会退出,因此有必要对其进行监控并自动重启,supervisor可满足需求,加上其用python写成,可以独自进行二次开发(supervisor的代码值得学习)。本文是对以往部分项目进行一个整理,作为参考资料归档。

1、离线安装supervisor

supervisor下载地址:

https://files.pythonhosted.org/packages/ca/1f/07713b0e1e34c312450878801d496bce8b9eff5ea9e70d41ff4e299b2df5/supervisor-4.1.0-py2.py3-none-any.whl

setuptools的下载地址:

https://files.pythonhosted.org/packages/d9/de/554b6310ac87c5b921bc45634b07b11394fe63bc4cb5176f5240addf18ab/setuptools-41.6.0-py2.py3-none-any.whl

先安装setuptools

1
2
unzip  setuptools-41.6.0.zip && cd  setuptools-41.6.0
python setup.py install

再安装supervisor

1
2
3
4
5
6
7
unzip  supervisor-4.1.0.tar.gz && cd supervisor-4.1.0
python setup.py install

# 测试是否安装成功
[root@~d]# python
>>> import supervisor
>>>

2、配置supervisor环境变量

很多网上教程在安装完supervisor后,都会给出如下提示:

在/etc/supervisor目录下生成配置文件

1
echo_supervisord_conf>/etc/supervisord.conf

但如果echo_supervisord_conf或者supervisord 二进制程序所在目录没有配到PATH环境变量的话,那么提示未找到对应的命令

1
2
[root@wap ~]# echo_supervisord_conf>/etc/supervisord.conf
-bash: echo_supervisord_conf: command not found

查找echo_supervisord_conf 在哪个目录下

2.1 PATH的问题

一般会在python的安装目录下,例如/usr/local/python27/bin 或者在编译安装python所设定的路径

[root@wap~]# which python3.5 /usr/local/bin/python3.5

但会有例外:

很多人安装python后,并没有把python的bin路径设到PATH里,而是直接把新安装的python 路径通过软链接的方式覆盖旧python,例如下面所示:

ln -s /usr/bin/python3.5 /usr/bin/python

虽然这种方式在可以启动python3.5,但一旦安装新的库后,这些库所在路径不是位于python3.5目录下,而是位于系统默认的bin目录下,如下面所示:

1
2
[root@wap ~]# ls /usr/bin/
flask python3.5 pyvenv-3.5 pip3 supervisorctl supervisord echo_supervisord_conf

这里flask库和supervisor库都在/usrl/bin/目录下
而此时查看系统系统的path变量,centos最初始的path配置如下

1
2
3
4
5
6
7
# .bash_profile
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/bin
export PATH

显然没有加入python的环境变量,修改后如下:

1
2
3
4
5
6
7
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
PATH=$PATH:$HOME/bin:/usr/bin/
export PATH

到此,supervisor的相关命令可在shell直接使用

1
2
3
4
5
[root@wap ~]# echo_supervisord_conf 
; Sample supervisor config file.
;
; For more information on the config file, please see:
......

3、 将supervisor配置成service,并加入开机自启

3.1 加入service

离线安装supervisor后,还需配置开机启动service,这里要注意:

需要将 daemon "supervisord -c /etc/supervisord.conf "

改为daemon "/usr/bin/supervisord -c /etc/supervisord.conf "

完整的service配置如下:

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
[root@wap ~]# vi /etc/rc.d/init.d/supervisord

#!/bin/bash

# source function library
. /etc/rc.d/init.d/functions
RETVAL=0
start() {
echo -n $"Starting supervisord: "
daemon "/usr/bin/supervisord -c /etc/supervisord.conf "
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/supervisord
}

stop() {
echo -n $"Stopping supervisord: "
killproc supervisord
echo
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/supervisord
}

restart() {
stop
start
}

case "$1" in
start)
start
;;
stop)
stop
;;
restart|force-reload|reload)
restart
;;
condrestart)
[ -f /var/lock/subsys/supervisord ] && restart
;;
status)
status supervisord
RETVAL=$?
;;
*)
echo $"Usage: $0 {start|stop|status|restart|reload|force-reload|condrestart}"
exit 1
esac

exit $RETVAL

修改文件权限为755,并设置开机启动

1
2
chmod 755 /etc/rc.d/init.d/supervisord
chkconfig supervisor on
3.2 修改默认的/etc/supervisord.conf
1
2
3
4
5
6
7
8
9
10
11
[unix_http_server]
file=/var/run/supervisor.sock

[supervisord]
logfile=/var/log/supervisor/supervisord.log ; 修改为 /var/log 目录,避免被系统删除
pidfile=/var/run/supervisord.pid
...
[supervisorctl]
; 和'unix_http_server'里面的设定匹配
serverurl=unix:///var/run/supervisor.sock

注意:/var/log/supervisor/supervisord.log需要手动创建

3.4、配置supervisord的web界面
1
2
3
4
[inet_http_server]      
port=*:36700
username=***
password=***
3.5、配置管理进程

配置管理进程有两种方式,一种是直接在supervisord.conf文件写入相关进程配置,另外一种是在某个目录下,为每个进程单独创建一份配置文件,然后把这些配置文件include到supervisord.conf,已防止supervisord.conf的全局配置被错误修改。

1
2
3
4
5
6
7
8
# /etc/supervisor/config,用于存放全部进程管理的配置文件
[root@wap ~]# mkdir -p /etc/supervisor/config

# 在/etc/supervisord.conf全局配置文件中的include参数,
# 将/etc/supervisor/config目录添加到include中

[include]
files =/etc/supervisor/config/*.ini

这里以配置flask两个小项目作为示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@wap ~]#  vi /etc/supervisor/config/flask_app_1.init
[program:flask_app_1]
command=python /opt/flask_app_1/app.py
# 日志目录需要手动创建,文件名由supervisor创建
stdout_logfile=/etc/supervisor/logs/flask_app_1.log
# stdout日志文件大小,默认50MB,这里设为10M
stdout_logfile_maxbytes=10MB
# 限制保存最近10个日志
stdout_logfile_backups=10
# 在 supervisord 启动的时候也自动启动
autostart=true
# 把stderr重定向到stdout,默认false
redirect_stderr = true
# 程序异常退出后自动重启
autorestart=true
# 启动5秒后若没有异常退出,则认为该服务已经正常启动
startsecs=5
user=root ;默认使用root用户
priority=10 ;该进程的优先级
stopasgroup=true ;默认为false,进程被杀死时,是否向这个进程组发送stop信号,包括子进程
killasgroup=true ;默认为false,向进程组发送kill信号,包括子进程

flask_app_2同上配置,注意实际使用中,应与相关需求或功能命名。

4、启动supervisor并测试

这里因为已经将supervisor配置成service,故不需要再使用

supervisord -c /etc/supervisord.conf 这样的命令启动supervisor

1
2
3
4
5
6
7
8
9
10
11
[root@wap ~]# service supervisor start
Starting supervisord: [ OK ]

[root@wap ~]# service supervisor status
supervisord (pid 18921) is running...

[root@wap ~]# service supervisor stop
Stopping supervisord: [ OK ]
[root@wap ~]# service supervisor restart
Stopping supervisord: [ OK ]
Starting supervisord: [ OK ]

以上说明supervisor的service配置是成功的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 查看已经被管理进程,这里有两种方式,一种在web 页面查看与操作,另外一种则用cli方式查看
# cli查看相关被管理进程服务
[root@portal py_apps]# supervisorctl
flask_app_1 RUNNING pid 191047, uptime 0:11:04
flask_app_2 RUNNING pid 191047, uptime 0:11:04
supervisor>

# 重启几次flask,查看其日志
[root@wap ~]# cat /etc/supervisor/logs/flask_app_1.log
* Serving Flask app "app" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
* Serving Flask app "app" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off

通过web查看和管理进程
在这里插入图片描述

5、supervisor分布式管理服务

  例如在serverA放了app1,serverB放了app2,serverC放了app3,而且每个server还有自行开发的其他采集模块等,因supervisor只能管理单机上的进程,对于不同服务器上的进程管理,则需要借助其他工具:例如cesi,地址:https://github.com/Gamegos/cesi。它可以实现跨服务器管理进程。当然我们完全可以基于supervisor进行开发,利用它提供的rpc接口,也可以开发出集群管理工具。但不建议这么做,考虑到还需要主力攻项目,这些通用工具能用第三方可优先使用。本文不再对cesi进行测试。