返回介绍

进程管理 Supervisor

发布于 2025-04-20 18:52:15 字数 8554 浏览 0 评论 0 收藏

Supervisor 是一个用 Python 实现的进程管理工具,可以很方便地启动、重启、关闭、查看进程(不仅仅是 Python 进程)。除了对单个进程的控制,它还可以同时操作多个进程。除此之外它还能监控进程,当进程由于某种原因崩溃或者误操作杀掉后,自动重启并发送事件通知。

我们先安装它:

> pip install supervisor

Supervisor 组件

Supervisor 包含如下 4 种组件。

1.Supervisord:服务端程序,它的主要功能是启动 Supervisord 服务及其管理的子进程,记录日志,重启崩溃的进程等。

2.Supervisorctl:命令行客户端程序,它提供一个类似 Shell 的接口,通过 UNIX 域套接字或者 TCP/IP 套接字使用 XML_RPC 协议与 Supervisord 进程进行数据通信。它的主要功能就是管理(启动、关闭、重启、查看状态等)子进程。

3.Web Server:实现了在界面上管理进程,还能查看进程日志和清除日志。Web Server 其实是通过 XML_RPC 来实现的,可以向 Supervisord 请求数据。它配置在[inet_http_server]块里面。

4.XML_RPC 接口:可以通过 XML-RPC 协议对 Web Server 进行远程调用,达到和 Supervisorctl 以及 Web Server 一样的管理功能。

配置 Supervisor

Supervisor 的配置文件一般都叫作 supervisord.conf。启动 Supervisord 的时候会按照如下的路径寻找配置文件:

  • 当前目录下的 supervisord.conf($CWD/etc/supervisord.conf)。
  • 当前目录的 etc 目录下的 supervisord.conf($CWD/etc/supervisord.conf)。
  • 相对于可执行文件 supervisord 的上一级的 etc 目录下的 supervisord.conf(../etc/super-visord.conf)。
  • 相对于可执行文件 supervisord 的上一级的 supervisord.conf(../supervisord.conf)。

可以使用-c 选项指定不符合如上要求的配置文件路径。

先创建一个统一的存放日志的目录,并让 ubuntu 这个用户成为其拥有者:

> sudo mkdir/var/log/supervisord
> sudo chown ubuntu:ubuntu/var/log/supervisord-R

下面的例子将通过 Supervisor 管理 Memcached 和 Gunicorn:

[unix_http_server]
file=/tmp/supervisor.sock;监听 HTTP/XML-RPC 请求。分号表示之后的内容是注释
;username=dongwm;登录管理后台的用户名
;password=123;username 和 password 在安全的网络中不需要设置,所以都是注释的

[inet_http_server];提供 Web 管理界面
port=0.0.0.0:5000;Web 管理后台运行的 IP 和端口,需要考虑安全性
username=dongwm
password=123

[supervisord]
logfile=/var/log/supervisord/supervisord.log         ;日志文件
logfile_maxbytes=50MB                                ;日志文件大小限制,超过会切分。设置
       为 0 表示不限制
logfile_backups=20                                   ;切分后的日志保留的份数
loglevel=error                                       ;日志级别,其他可选项为 info, debug,
     warn, trace
pidfile=/var/run/supervisord.pid
nodaemon=false                                       ;使用 daemon 的方式启动
minfds=1024                                          ;可以打开的文件描述符的最小值
minprocs=200                                         ;可以打开的进程数的最小值
user=ubuntu                                          ;启动 supervisord 进程使用的用户,虽然
     默认就是当前用户,但是指定 user 是一个好习惯

[rpcinterface:supervisor]
supervisor.rpcinterface_factory=supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///tmp/supervisor.sock                ;使用 UNIX 域套接字的方式,文件路径必须
    和 unix_http_server 里面的设定匹配
prompt=web_develop;定义提示文本,常用来区分不同的环境。使用清晰的提示能减少操作出错
[include];包含其他的配置文件,本例因为演示才把全部配置放在了一起,如果管理的进程较多,应该按一定规则分散到不同的配置文件中
files=/etc/supervisor/conf.d/*.conf

[program:app_chapter6];每个 program 就是一个(组)进程
command=gunicorn-w 3 chapter6.section1.run:app-b 0.0.0.0:9000;启动命令
autostart=true;在 Supervisord 启动的时候也自动启动
autorestart=true;程序异常退出后自动重启
startsecs=5;启动 5 秒后没有异常退出,就当作已经正常启动了
startretries=3;启动失败自动重试次数,默认是 3 次
user=ubuntu
priority=100;优先级设置。低优先级会先启动,后关闭。应用进程应该是优先级最高
redirect_stderr=true;把错误日志重定向到输出的日志中。当然可以把错误日志分开存放,需要使用 stderr_logfile 参数
stdout_logfile=/var/log/supervisord/chapter6.log;指定输出的日志的文件路径
directory=%(ENV_HOME)s/web_develop;启动时会先切换目录进来,保证启动的时候的相对路径正确性
stdout_logfile_maxbytes=200MB;输出日志文件大小限制,超过会切分。设置为 0 表示不限制

[program:memcached]
priority=10
numprocs=2;使用进程组
numprocs_start=2;进程组的数从 2 开始计数,因为 numprocs 是 2,也就是使用 2 和 3。如果不指定则是 0 和 1
process_name=1121%(process_num)s;当 numprocs>1 进程名字就需要带 process_num 变量
command=memcached-m 64-p 1121%(process_num)d-l 127.0.0.1;启动多个进程,由于
     process_num 不同而启动命令不同
redirect_stderr=true
stdout_logfile=/var/log/supervisord/memcached.log
stopasgroup=false;如果设置为 true,当进程收到 stop 信号时,会自动将该信号发给该进程的子进程
killasgroup=false;如果设置为 true,当进程收到 kill 信号时,会自动将该信号发给该进程的子进程

[eventlistener:listener];Supervisor 提供事件监听和通知机制
buffer_size=30;增大事件队列的长度,如果监控的事件量大,不能处理的事件会被抛弃
priority=-1;事件监控的优先级应该最低
command=python%(ENV_HOME)s/web_develop/chapter7/section1/listener.py
events=PROCESS_STATE_EXITED,PROCESS_STATE_STOPPED,PROCESS_STATE_FATAL,TICK_60;检测如上三种事件,全部事件类型可以查看[Event Types](http://supervisord.org/events.html#event-types)
stdout_logfile=/var/log/supervisord/listener.log
stderr_logfile=/var/log/supervisord/listener.log;eventlistener 类型不能使用
   redirect_stderr=true
stdout_events_enabled=false
stderr_events_enabled=false

Supervisor 的注释要使用分号。在上述配置中,program 块中指定了要管理的进程,但是要注意,被管理的进程不能使用 daemon 模式,必须在前台运行。

ENV_HOME 是 Supervisor 内置的变量之一,表示当前用户的家目录。

在 eventlistener 块中使用了自定义的事件监听脚本 listener.py,它用来把事件日志写到文件中:

import sys
from datetime import datetime
from supervisor import childutils #通过 childutils 模块来创建事件监听

def write_log(headers, payload):
    if not headers['eventname'].startswith('PROCESS_STATE_'):
        return
    f=open('/tmp/log.txt', 'a')
    f.write(str(headers)+'\n\n') #为了查看事件通知的格式
    pheaders, pdata=childutils.eventdata(payload+'\n')

    pheaders['dt']=datetime.now() #我们对事件的头信息做了扩充,添加当前时间

    msg=('[{dt}]Process{processname}in group{groupname}exited '
         'unexpectedly (pid{pid}) from state{from_state}\n').format(
      **pheaders)
    f.write(msg) #当出现符合条件的三种事件,会记录如上日志
    f.flush()
    f.close()

def main():
    while 1:
        headers, payload=childutils.listener.wait(sys.stdin, sys.stdout)
        write_log(headers, payload)
        childutils.listener.ok(sys.stdout)


if__name__=='__main__':
   main()

Supervisor 有官方的插件集合 Superlance(https://github.com/Supervisor/superlance ),提供监控内存的使用、发送报警邮件等功能,但是建议只把它用作自定义脚本实现时的参考。更多第三方应用和插件可以在 Third Party Applications and Libraries(http://supervisord.org/plugins.html )找到。

使用 Supervisor

首先启动 Supervisord 进程:

> supervisord-c chapter7/section1/supervisord.conf

进程会以 daemon 的方式后台运行。使用 Supervisorctl 连接它:

> supervisorctl-c chapter7/section1/supervisord.conf
app_chapter6 RUNNING pid 12316, uptime 0:00:11
listener             RUNNING pid 12313, uptime 0:00:11
memcached:11212      RUNNING pid 12314, uptime 0:00:11
memcached:11213      RUNNING pid 12315, uptime 0:00:11
web_develop>

可以看到启动了两个 Memcached 进程、listener 进程和应用(Gunicorn)进程。现在管理进程:

web_develop>stop memcached:11212 #关闭 memcached:11212 进程
memcached:11212:stopped
web_develop>status
app_chapter6
STARTING
listener              RUNNING pid 17604, uptime 0:02:15
memcached:11212       STOPPED Jun 04 01:21 AM
memcached:11213       RUNNING pid 17606, uptime 0:02:15
web_develop>update # 更新 supervisord.conf 配置后,可以使用这个命令让配置生效
web_develop>start memcached:11212 #重新启动
memcached:11212:started
web_develop>pid app_chapter6 #查看进程 id
12316
web_develop>maintail #查看 Supervisor 日志
web_develop>tail-10 listener #查看 listener 进程日志,支持进程名自动补全
2
OKREADY

通过 help 命令可获取全部命令的列表。管理命令可以作为 supervisorctl 的参数来使用:

> supervisorctl-c chapter7/section1/supervisord.conf stop memcached:11212

由于监听程序会监听 PROCESS_STATE_STOPPED,所以会记录停止 memcached:11212 的事件。查看/tmp/log.txt,就会看到如下记录:

{'ver':'3.0', 'poolserial':'3', 'len':'67', 'server':'supervisor', 'eventname':'
    PROCESS_STATE_STOPPED', 'serial':'3', 'pool':'listener'}

[2016-06-04 01:21:11.914393]Process 11212 in group memcached exited unexpectedly (pid
     12314) from state STOPPING

还可以通过事件返回的结果来组织内容发送邮件、HTTP 请求、短信,甚至触发某些其他操作。

可以访问 http://localhost:5000,看到 HTTP 的管理页面。因为在[inet_http_server]块中配置了用户和密码,所以访问的时候是有用户访问验证的。

除此之外,还可以通过 XML_RPC 接口来管理进程:

In : import xmlrpclib
In : server=xmlrpclib.Server('http://dongwm:123@localhost:5000/RPC2')
In : server.supervisor.stopProcess('memcached:11212')
Out: True
In :  server.supervisor.getProcessInfo('memcached:11212')
Out:
{'description':'Jun 04 01:31 AM',
 'exitstatus':0,
 'group':'memcached',
 'logfile':'/var/log/supervisord/memcached.log',
 'name':'11212',
 'now':1465003888,
 'pid':0,
 'spawnerr':'',
 'start':1465003311,
 'state':0,
 'statename':'STOPPED',
 'stderr_logfile':'',
 'stdout_logfile':'/var/log/supervisord/memcached.log',
 'stop':1465003867}

In:server.supervisor.startProcess('memcached:11212')
Out:True

支持的全部命令可以使用 server.system.listMethods() 获取。

之前的例子是在虚拟环境中实现的,如果 Supervisor 安装在全局而要使用虚拟环境,可以通过如下两种方法。

1.把 program 项中的 command 改成完整路径:

[program:app_chapter6]
command=%(ENV_HOME)s/.virtualenvs/venv/bin/gunicorn-w 3 chapter6.section1.app:
      app-b 0.0.0.0:9000

2.使用参数 environment 把全局环境目录放进 PATH:

[program:app_chapter6]
environment=PATH=%(ENV_HOME)s/.virtualenvs/venv/bin:%(ENV_PATH)s
command=gunicorn-w 3 chapter6.section1.app:app-b 0.0.0.0:9000

除了使用 Supervisor 管理进程,还可以选择 Upstart 和 Systemd 来管理,推荐 Systemd,因为它的设计更优秀,越来越多的 Linux 发行版已经选择它。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。