Supervisor 是一个客户端/服务器系统,允许用户控制类 UNIX 操作系统上的多个进程,能将一个普通的命令行进程变为后台daemon,并监控进程状态,当进程中断时也可以重新启动,在python开发中比较常见。
介绍
优点
官网上列举的优点有:
- 简单:可通过简单易学的 INI 样式配置文件进行配置
- 集中:提供了一个启动、停止和监控进程的地方。可以单独或成组控制进程。
- 高效:Supervisor 通过 fork/exec 启动其子进程,子进程不作为守护进程。进程终止时,操作系统会立即向 Supervisor 发出信号,而不像某些解决方案那样依赖麻烦的 PID 文件和定期轮询来重新启动失败的进程。
- 可扩展:Supervisor 有一个简单的事件通知协议,任何语言编写的程序都可以使用它来监控它,还有一个 XML-RPC 接口用于控制。它还内置了可供 Python 开发人员利用的扩展点。
- 兼容的:Supervisor 几乎可以在除 Windows 之外的所有平台上运行(这个就很尴尬,windows server不行也能叫兼容吗?)
- 可靠的:存在多年,并且已在许多服务器上使用
两个组件
supervisord
和 supervisorctl
是supervisor
工具中的两个主要组件
supervisord
是 Supervisor 的服务器部分,负责启动、管理和监控所有由其配置的子进程。还可以记录其子进程stdout
和stderr
输出,以及生成和处理与子进程生命周期中的点相对应的"事件"。supervisorctl
是一个命令行客户端,用于与supervisord
交互。它提供了一个类似shell的界面,用户可以连接到不同的supervisord
进程
安装与运行
因为不支持在windows上运行,我这里用了wsl(用其他的虚拟环境也可以)
- 搭建python的虚拟环境和安装对应的包
shell
python3 -m venv venv
source venv/bin/activate
pip install -i https://mirrors.aliyun.com/pypi/simple --upgrade pip
pip install -i https://mirrors.aliyun.com/pypi/simple --upgrade setuptools
pip install -i https://mirrors.aliyun.com/pypi/simple supervisor
- 导出配置
shell
venv/bin/echo_supervisord_conf > supervisord.conf
- 修改配置(在启动之前,我们至少要添加一个程序配置)
shell
vim supervisord.conf
ini
[program:foo]
command=/bin/cat
- 运行:
supervisord -c supervisord.conf -n
,如果看到success就可以了
这里的命令行选项含义是:
-c FILE, --configuration=FILE:Supervisord配置文件的路径。
-n, --nodaemon:在前台运行supervisord 。
- 使用
supervisorctl
确认下状态:venv/bin/supervisorctl status all
,如果看到RUNNING,说明配置中的foo程序就在运行了
可以使用"一次性"命令调用 supervisorctl 可执行文件,像我上面写的
venv/bin/supervisorctl status all
也可以进入控制台,
venv/bin/supervisorctl
然后再执行status all
- 结束:Ctrl + C就行,假如是后台运行的话,可以这样结束运行
shell
ps aux | grep supervisord
sudo pkill supervisord
配置篇
上面的演示使用的是导出的配置,真正实战肯定是要用自定义的配置,方便管理。我这里给比较常见的配置注释了,更具体的最好还是去官网查阅
ini
[unix_http_server]
file=/tmp/supervisor.sock ; 套接字文件,只有在supervisor运行时候才会创建,它将允许本地的 supervisorctl 或其他工具通过套接字文件与 supervisord 通信。
chmod=0700 ; 套接字文件的权限(这也是默认值,仅限所有者读写)
username=user ; 需要身份验证时的用户名,这样使用 supervisorctl 需要输入用户名和密码
password=pass ; 需要身份验证时的密码
[supervisord]
logfile=/tmp/supervisord.log ; 定义 supervisord 的日志文件路径。
logfile_maxbytes=50MB ; 设置日志文件的最大大小。
logfile_backups=10 ; 会保留最近 10 个轮转的日志文件,超过数量的旧日志将被删除。
loglevel=info ; 日志记录级别; 其他的有debug,warn,trace等
pidfile=/tmp/supervisord.pid ; PID 文件记录 supervisord 进程的 ID,方便后续管理(如停止、重启)。
nodaemon=false ; 设置 supervisord 是否以守护进程(daemon)模式运行。
silent=false ; 定义 supervisord 是否在非守护模式下隐藏输出,false:输出日志到控制台(适合调试)。
minfds=1024 ; 定义 supervisord 管理的最小文件描述符数量(在 Linux/Unix 系统中,文件描述符是进程与内核之间通信的桥梁,感兴趣可以了解下,这里就用默认配置)
minprocs=200 ; 定义 supervisord 管理的最小进程数
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface ; 基础配置,必须保留,创建并注册主 RPC 接口
[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ;用来访问 Supervisord 服务器的 URL,和上面的 unix_http_server 部分的 file 选项对应。
[program:celery]
command=celery -A celery_app worker --loglevel=INFO --logfile=/root/supervisor/log/worker.log ;启用celery
autostart=true ;设置 Supervisor 在启动时是否自动启动该程序。
autorestart=true ; 如果程序异常退出,是否自动重启。
restartsecs=5 ;重启前的等待时间(秒)
startretries=3 ;启动失败时,Supervisor 重试次数。
; 日志配置:标准输出(stdout)和标准错误(stderr)日志
stderr_logfile=/root/supervisor/log/celery_worker.err.log
stderr_logfile_maxbytes=10MB
stderr_logfile_backups=3
stdout_logfile=/root/supervisor/log/celery_worker.out.log
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=3
-
注意,我这里给
unix_http_server
设置了用户和密码,这样使用supervisorctl
工具时需要输入密码了 -
设置重启时,一定要注意,如果这个命令会占用资源/消耗大量cpu,那么反复重启可能会有比较严重的后果
supervisorctl 操作篇
查看进程
status celery
:status可以查看进程的状态,如果后面接all,就是查看所有的进程- 直接输入
help
可以查看所有命令,其实大部分命令的含义可以直观理解的
新增进程
- 修改配置,我在配置中增加了一段
ini
[program:foo]
command=/bin/cat
- 在
supervisorctl
的控制台中依次执行以下命令,就可以看到foo进程执行了
shell
reread
update
status all
- 修改配置也是类似操作
停止进程
-
status foo
:停止foo这个进程,停止后再次查看状态,会有如下显示foo STOPPED Dec 13 06:07 PM
启动进程
start foo
:启动foo这个进程restart foo
:重新启动foo这个进程
移除进程
remove foo
:移除foo
这个进程- 注意,这里并没有把配置中的
foo
删除,再次reread
仍然可以读到配置