文章目录

  • 常用命令
  • 简介
  • 安装
  • 创建配置文件
  • 开机自启
  • 初试
  • Web 界面
  • 配置文件
  • 子进程配置模板
  • 可用变量
  • supervisorctl 命令
  • Supervisor 组件
  • 卸载
  • 遇到的坑
  • 参考文献


常用命令

修改配置并重启子进程

vim /etc/supervisor/conf.d/xxx.conf
supervisorctl reread
supervisorctl update
supervisorctl restart xxx
watch -n 1 "supervisorctl status"

查看进程状态

supervisorctl status

查看 supervisord 的进程

ps -ef | grep supervisord


简介

Supervisor 是一款 Python 开发的进程管理系统,允许用户监视和控制 Linux 上的进程,能将一个普通命令行进程变为后台守护进程,异常退出时能自动重启

安装

Supervisor 支持 Linux 和 Mac,不支持 Windows

本文系统为 Ubuntu,supervisor==4.2.4

pip3 install supervisor

创建配置文件

sudo echo_supervisord_conf > /etc/supervisord.conf

若报错 -bash: /etc/supervisord.conf: Permission denied,需要切换到 root

sudo su root

输出配置文件

cat /etc/supervisord.conf

创建子进程配置文件路径

mkdir -p /etc/supervisor/conf.d/

修改配置文件

sudo vim /etc/supervisord.conf

将最后一部分改为

[include]
files=/etc/supervisor/conf.d/*.conf

其余改成以下内容

[unix_http_server]
file=/var/run/supervisor.sock;
chmod=0777;  所有用户可操作

[supervisord]
logfile=/var/log/supervisord.log;

pidfile=/var/run/supervisord.pid;

[supervisorctl]
serverurl=unix:///var/run/supervisor.sock;


开机自启

以 Ubuntu 为例

创建启动脚本

sudo curl https://raw.githubusercontent.com/Supervisor/initscripts/master/ubuntu > /etc/init.d/supervisord

添加执行权限

sudo chmod +x /etc/init.d/supervisord

查看 supervisord 的 pidfile 路径

which supervisord
which supervisorctl
cat /etc/supervisord.conf | grep logfile
cat /etc/supervisord.conf | grep pidfile
#  pidfile=/var/run/supervisord.pid;

修改启动脚本的变量 DAEMON、SUPERVISORCTL、LOGDIR、PIDFILE、DAEMON_OPTS 与上一致

sudo vim /etc/init.d/supervisord

DAEMON=/usr/local/bin/supervisord
SUPERVISORCTL=/usr/local/bin/supervisorctl

LOGDIR=/var/log/supervisord.log
PIDFILE=/var/run/supervisord.pid

DAEMON_OPTS="-c /etc/supervisord.conf $DAEMON_OPTS"

配置

sudo update-rc.d supervisord defaults
sudo service supervisord stop
sudo service supervisord start
systemctl status supervisord.service  # 查看服务状态

以 CentOS 为例

查看 supervisord 的位置,得到结果如 /usr/local/bin/supervisord

which supervisord

查看 supervisord 的位置,得到结果如 /usr/local/bin/supervisorctl

which supervisorctl

创建服务文件

sudo vim /usr/lib/systemd/system/supervisord.service

填入

[Unit]
Description=Supervisor daemon

[Service]
Type=forking
ExecStart=/usr/local/bin/supervisord
ExecStop=/usr/local/bin/supervisorctl $OPTIONS shutdown
ExecReload=/usr/local/bin/supervisorctl $OPTIONS reload
KillMode=process
Restart=on-failure
RestartSec=42s

[Install]
WantedBy=multi-user.target

查看是否已启动 supervisord,若已启动,杀进程

ps -ef | grep supervisord
supervisorctl stop all
kill -9 xxx

配置

sudo systemctl daemon-reload  # 重载系统管理配置
sudo systemctl enable supervisord  # 开机自启动
sudo systemctl start supervisord  # 启动服务
systemctl status supervisord  # 查看服务状态

初试

启动 supervisord

supervisord
或
supervisord -c /etc/supervisord.conf

查看版本

supervisord -v

查看进程状态(还没配程序,此时空输出)

supervisorctl status

编写简单的 Shell 脚本

vim /tmp/echo_time.sh

内容如下

#!/bin/bash
while : 
do
    echo `date '+%Y-%m-%d %H:%m:%S'`
    sleep 1
done

简单运行,Ctrl + C

sh /tmp/echo_time.sh

创建子进程配置文件

vim /etc/supervisor/conf.d/echo_time.conf

内容如下

[program:echo_time]                       ; 项目名
command=sh /tmp/echo_time.sh              ; 脚本执行命令
autostart=true                            ; 在supervisor启动时自动启动,默认为true
autorestart=true                          ; 在意外退出时重新启动,默认为unexpected
startsecs=10                              ; 子进程启动多少秒后状态为running则认为启动成功,默认为1
startretries=3                            ; 尝试启动的最大次数,默认为3
exitcodes=0                               ; 进程的预期退出代码列表,默认为0
stopsignal=QUIT                           ; 终止进程的信号,默认为TERM
stopwaitsecs=10                           ; 在SIGKILL之前等待的最大秒数,默认为10
user=root                                 ; 在某用户下设置uid来启动程序,默认不切换用户
redirect_stderr=true                      ; 是否合并stderr到stdout,默认为false
stdout_logfile=/tmp/echo_time.stdout.log  ; stdout的输出文件,默认为AUTO
stdout_logfile_maxbytes=50MB              ; stdout最大文件大小,默认为50MB
stdout_logfile_backups=10                 ; stdout文件备份数,设为0则不备份,默认为10

重新读取配置并更新子进程

supervisorctl reread
supervisorctl update

再次查看进程状态

supervisorctl status
watch -n 1 "supervisorctl status"

管理python进程 python进程管理supervisor_子进程

动态输出运行情况

tail -f /tmp/echo_time.stdout.log

效果

管理python进程 python进程管理supervisor_linux_02


Web 界面

修改配置文件

sudo vim /etc/supervisord.conf

取消注释

[inet_http_server]
port=*:9001                ; 此处改为*便于调试

重启 supervisord

supervisorctl reload

查看本机 IP

hostname -I

访问 http://127.0.0.1:9001(把 127.0.0.1 改成上述 IP)

管理python进程 python进程管理supervisor_管理python进程_03


配置文件

服务器进程使用的配置文件一般为 /etc/supervisord.conf,格式为 Windows-INI

子进程配置文件在文件夹 /etc/supervisor/conf.d/,可通过上述配置文件的最后一行指定


子进程配置模板

[program:echo_time]                       ; 项目名
command=/Envs/xxx/bin/gunicorn -w 4 -b 127.0.0.1:5000 -k gevent main:app              ; 脚本执行命令
process_name=%(program_name)s             ; 进程名,默认为%(program_name)s,同项目名
numprocs=1                                ; 启动的程序实例数,默认为1
directory=/data/code/project              ; 脚本执行路径
umask=022                                 ; 进程掩码,默认无
priority=999                              ; 相对启动优先级,数值越小越优先,默认为999
autostart=true                            ; 在supervisor启动时自动启动,默认为true
autorestart=true                          ; 在意外退出时重新启动,默认为unexpected
startsecs=10                              ; 子进程启动多少秒后状态为running则认为启动成功,默认为1
startretries=3                            ; 尝试启动的最大次数,默认为3
exitcodes=0                               ; 进程的预期退出代码列表,默认为0
stopsignal=QUIT                           ; 终止进程的信号,默认为TERM
stopwaitsecs=10                           ; 在SIGKILL之前等待的最大秒数,默认为10
stopasgroup=false                         ; 是否把整个子进程的进程组停止,发送stop信号,默认为false
killasgroup=false                         ; 是否把整个子进程的进程组停止,发送kill信号,默认为false
user=root                                 ; 在某用户下设置uid来启动程序,默认不切换用户
redirect_stderr=true                      ; 是否合并stderr到stdout,默认为false
stdout_logfile=/tmp/echo_time.stdout.log  ; stdout的输出文件,默认为AUTO
stdout_logfile_maxbytes=50MB              ; stdout最大文件大小,默认为50MB
stdout_logfile_backups=10                 ; stdout文件备份数,设为0则不备份,默认为10
stdout_capture_maxbytes=1MB               ; capture管道大小,默认为0,关闭管道
stdout_events_enabled=false               ; 当进程写stdout时是否触发PROCESS_LOG_STDOUT事件,默认为false
stderr_logfile=/tmp/echo_time.stderr.log  ; stderr的输出文件,默认为AUTO
stderr_logfile_maxbytes=50MB              ; stderr最大文件大小,默认为50MB
stderr_logfile_backups=10                 ; stderr文件备份数,设为0则不备份,默认为10
stderr_capture_maxbytes=1MB               ; capture管道大小,默认为0,关闭管道
stderr_events_enabled=false               ; 当进程写stderr时是否触发PROCESS_LOG_STDERR事件,默认为false
environment=A="1",B="2"                   ; 环境变量,默认无
serverurl=AUTO                            ; 进入supervisord的URL,默认为AUTO

简化版

[program:echo_time]
command=/Envs/xxx/bin/gunicorn -w 4 -b 127.0.0.1:5000 -k gevent main:app
directory=/data/code/project
autorestart=true
startsecs=10
stopsignal=QUIT
user=root
redirect_stderr=true
stdout_logfile=/var/log/%(program_name)s.log
environment=A="1",B="2"

stopasgroup=true

根据 Option to create directory of specified log files,不会自动创建日志目录,不存在的话会报错

TODO:`stdout_logfile` 可改为 ``,放在与项目同一目录下


可用变量

查看环境变量,含有的都可用

env

Supervisor 自带的变量

变量名

含义

group_name

here

配置文件目录

host_node_name

numprocs

process_num

program_name

程序名


supervisorctl 命令

改动某配置文件,重载

supervisorctl update

新增某配置文件,重载

supervisorctl reread

重启 supervisord

supervisorctl reload

查看所有进程状态

supervisorctl status

查看指定进程状态

supervisorctl status <name>

启动所有子进程

supervisorctl start all

启动指定子进程

supervisorctl start <name>

重启所有子进程

supervisorctl restart all

重启指定子进程

supervisorctl restart <name>

停止所有子进程

supervisorctl stop all

停止指定子进程

supervisorctl stop <name>

添加子进程到进程组

supervisorctl add <name>

从进程组移除子进程,需要先stop。注意:移除后,需要使用reread和update才能重新运行该进程

supervisorctl reomve <name>


Supervisor 组件

  • supervisord
    服务器部分称为 supervisord,负责启动子程序,响应客户端的命令,重新启动崩溃或退出的子进程,记录子进程的 stdout 和 stderr 输出等
    服务器进程使用的配置文件一般为 /etc/supervisord.conf,格式为 Windows-INI
    子进程配置文件在文件夹 /etc/supervisor/conf.d/
  • supervisorctl
    客户端命令行部分称为 supervisorctl ,可以连接到不同的 supervisord 进程,获取子进程状态,停止和启动子进程,以及获取一个正在运行的进程列表
  • Web Server
    可以通过浏览器访问 Web 用户界面进行 supervisorctl 操作
  • XML-RPC Interface
    可以通过接口 API 进行 supervisorctl 操作


卸载

dpkg -l | grep supervisor
sudo apt-get autoremove supervisor
sudo apt-get --purge remove supervisor
pip3 uninstall supervisor


遇到的坑

1. 启动时报错 Unlinking stale socket /tmp/supervisor.sock

杀掉进程,删除该文件,重新启动

sudo unlink /tmp/supervisor.sock
ps -ef | grep supervisord
kill 9 xxx

2. 报错 Error: Another program is already listening on a port that one of our HTTP servers is configured to use. Shut this program down first before starting supervisord.

杀掉进程,删除该文件,重新启动

sudo unlink /tmp/supervisor.sock
ps -ef | grep supervisord
kill 9 xxx

3. 普通用户 supervisorctl status 报错 error: <class ‘PermissionError’>, [Errno 13] Permission denied: file: /usr/local/lib/python3.8/site-packages/supervisor/xmlrpc.py line: 560

chmod 777 /tmp/supervisor.sock

4. Ubuntu 用 pip 安装找不到文件

把 supervisord 复制到 /usr/bin/ 目录下

或指定目录安装

pip3 install supervisor --install-option="--install-scripts=/usr/local/bin"

或全局安装(建议这种)

sudo -H pip3 install supervisor

5. 报错 unix:///tmp/supervisor.sock no such file

vim /etc/supervisord.conf

改成以下内容

[unix_http_server]
file=/var/run/supervisor.sock;

[supervisord]
logfile=/var/log/supervisord.log;

pidfile=/var/run/supervisord.pid;

[supervisorctl]
serverurl=unix:///var/run/supervisor.sock;

6. 报错 unknown error making dispatchers for ‘xxx’: EACCES

日志文件夹缺少写权限

chmod -R 777 /var/log/


参考文献

  1. Supervisor Documentation
  2. Supervisor GitHub
  3. Python supervisor 强大的进程管理工具
  4. Supervisor使用详解
  5. supervisor常用命令
  6. 服务器安装配置supervisor
  7. another program is already listening on a port that one of our HTTP servers is configured to use
  8. 4种方法来在Linux系统中查看IP地址
  9. Permession denied error when use supervisorctl
  10. supervisor(一)基础篇
  11. Supervisor - Can’t start supervisorctl as root or user (User is set in config)
  12. ubuntu server 16.04: cannot get supervisor to start automatically
  13. supervisor和Python多进程multiprocessing使用