Python实用工具之Supervisor详解:进程管理从入门到实战

一、Supervisor简介:是什么、怎么用、有何特点

Supervisor是一款基于Python开发的进程管理工具,主要用于监控、启动、停止和重启Unix-like系统上的进程,尤其适合管理长期运行的后台进程(如Web服务、爬虫脚本等)。其核心原理是通过fork/exec方式启动被管理进程,将其作为自己的子进程,实时监控进程状态,一旦进程意外退出便自动重启。

Supervisor采用MIT许可证,允许自由使用、修改和分发。优点是配置简单、轻量稳定、支持进程组管理和Web界面监控;缺点是仅支持Unix-like系统,不兼容Windows,且无法管理daemon化的进程。

二、Supervisor安装与环境配置

2.1 安装方式

Supervisor支持通过pip或系统包管理器安装,推荐使用pip以获取最新版本。

1. pip安装

打开终端,执行以下命令:

# 安装最新版本
pip install supervisor

# 验证安装是否成功(查看版本号)
supervisord --version

若输出类似4.2.5的版本号,则表示安装成功。

2. 系统包管理器安装(以Ubuntu为例)

对于Ubuntu/Debian系统,也可通过apt-get安装:

sudo apt-get update
sudo apt-get install supervisor

这种方式会自动配置系统服务,但版本可能略旧。

2.2 初始化配置文件

Supervisor的配置文件默认名为supervisord.conf,需要手动生成并配置。

1. 生成默认配置文件

执行以下命令生成默认配置模板:

# 生成配置文件到当前目录
echo_supervisord_conf > supervisord.conf

生成的配置文件包含所有可配置项及注释,新手可基于此修改。

2. 核心配置项说明

打开supervisord.conf,重点关注以下配置项(其余可保持默认):


[unix_http_server]
file=/tmp/supervisor.sock   ; Unix socket文件,用于与supervisorctl通信

[inet_http_server]          ; 启用Web管理界面(可选,建议开启)
port=127.0.0.1:9001         ; Web界面访问地址和端口
username=admin              ; 登录用户名
password=123456             ; 登录密码

[supervisord]
logfile=/tmp/supervisord.log ; 主进程日志文件
logfile_maxbytes=50MB        ; 日志文件最大大小
logfile_backups=10           ; 日志备份数量
loglevel=info                ; 日志级别(debug/info/warn/error/critical)
pidfile=/tmp/supervisord.pid ; 主进程PID文件
nodaemon=false               ; 是否以守护进程模式运行(false为前台,true为后台)

[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ; 与supervisord通信的socket路径

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

[include]
files = /etc/supervisor/conf.d/*.conf ; 包含的子配置文件路径(用于管理多个进程)

3. 配置文件部署(可选)

为了规范管理,建议将配置文件移动到系统标准目录:

# 创建配置目录
sudo mkdir -p /etc/supervisor/conf.d

# 移动主配置文件
sudo mv supervisord.conf /etc/supervisor/

# 修改include配置项(确保指向正确的子配置目录)
sudo sed -i 's|files = .*|files = /etc/supervisor/conf.d/*.conf|' /etc/supervisor/supervisord.conf

三、Supervisor基础使用:进程管理实战

Supervisor通过子配置文件管理具体进程,每个进程(或进程组)对应一个.conf文件,存放于/etc/supervisor/conf.d/目录下。下面通过3个实例演示不同场景的使用方式。

3.1 实例1:管理一个简单的Python后台脚本

假设我们有一个需要长期运行的Python脚本test_script.py,功能是每5秒打印一次当前时间并写入日志。

1. 编写Python脚本

创建/home/user/scripts/test_script.py

import time
import datetime

# 日志文件路径
LOG_FILE = "/home/user/scripts/test_script.log"

def main():
    while True:
        # 获取当前时间
        current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        # 日志内容
        log_content = f"[{current_time}] 脚本正常运行中...\n"
        # 打印到控制台并写入日志
        print(log_content, end="")
        with open(LOG_FILE, "a", encoding="utf-8") as f:
            f.write(log_content)
        # 休眠5秒
        time.sleep(5)

if __name__ == "__main__":
    main()

2. 编写Supervisor子配置文件

创建/etc/supervisor/conf.d/test_script.conf

[program:test_script]          ; 进程名称(唯一,用于supervisorctl操作)
command=/usr/bin/python3 /home/user/scripts/test_script.py  ; 启动命令(需指定Python解释器绝对路径)
directory=/home/user/scripts/  ; 工作目录
user=user                      ; 运行用户
autostart=true                 ; 随supervisord启动而启动
autorestart=true               ; 进程意外退出后自动重启
startretries=3                 ; 启动失败时的重试次数
redirect_stderr=true           ; 将 stderr 重定向到 stdout
stdout_logfile=/home/user/scripts/test_script_supervisor.log  ; 进程日志文件
stdout_logfile_maxbytes=10MB   ; 日志文件最大大小
stdout_logfile_backups=3       ; 日志备份数量

3. 启动Supervisor并加载配置

# 启动supervisord(指定配置文件路径)
sudo supervisord -c /etc/supervisor/supervisord.conf

# 重新加载配置(每次修改子配置文件后需执行)
sudo supervisorctl reread
sudo supervisorctl update

# 查看进程状态
sudo supervisorctl status

若输出test_script RUNNING pid 12345, uptime 0:01:23,表示进程启动成功。

4. 常用supervisorctl命令

# 启动进程
sudo supervisorctl start test_script

# 停止进程
sudo supervisorctl stop test_script

# 重启进程
sudo supervisorctl restart test_script

# 查看进程日志(实时输出)
sudo supervisorctl tail -f test_script

# 关闭supervisord
sudo supervisorctl shutdown

3.2 实例2:管理进程组(多个相关进程)

如果需要管理一组相关进程(如一个Web服务的API进程和定时任务进程),可使用[group]配置项将它们归类。

1. 编写两个Python脚本

  • api_server.py(模拟Web API服务):
from flask import Flask
app = Flask(__name__)

@app.route("/")
def index():
    return "API服务正常运行!"

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)
  • cron_task.py(模拟定时任务):
import time
import datetime

def main():
    while True:
        current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        print(f"[{current_time}] 定时任务执行中...")
        time.sleep(10)

if __name__ == "__main__":
    main()

注意:需安装flask依赖:pip install flask

2. 编写进程组配置文件

创建/etc/supervisor/conf.d/web_group.conf

[group:web_services]  ; 进程组名称
programs=api_server,cron_task  ; 组内进程名称(用逗号分隔)

[program:api_server]
command=/usr/bin/python3 /home/user/scripts/api_server.py
directory=/home/user/scripts/
user=user
autostart=true
autorestart=true
stdout_logfile=/home/user/scripts/api_server.log
stdout_logfile_maxbytes=10MB

[program:cron_task]
command=/usr/bin/python3 /home/user/scripts/cron_task.py
directory=/home/user/scripts/
user=user
autostart=true
autorestart=true
stdout_logfile=/home/user/scripts/cron_task.log
stdout_logfile_maxbytes=10MB

3. 加载配置并管理进程组

# 重新加载配置
sudo supervisorctl reread
sudo supervisorctl update

# 查看进程组状态
sudo supervisorctl status web_services:*

# 启动/停止整个进程组
sudo supervisorctl start web_services:*
sudo supervisorctl stop web_services:*

3.3 实例3:通过Web界面管理进程

Supervisor提供了Web界面,可直观地查看和操作进程,无需通过命令行。

1. 启用Web界面

确保supervisord.conf[inet_http_server]配置已开启(参考2.2节),然后重启supervisord:

sudo supervisorctl shutdown
sudo supervisord -c /etc/supervisor/supervisord.conf

2. 访问Web界面

打开浏览器,访问http://127.0.0.1:9001,输入配置的用户名(admin)和密码(123456),即可看到所有进程的状态。界面上提供了启动、停止、重启、查看日志等按钮,操作十分便捷。

四、实际案例:用Supervisor管理Django项目

在生产环境中,Django项目通常需要通过Gunicorn作为WSGI服务器运行,同时可能需要启动Celery处理异步任务。下面演示如何用Supervisor管理这两个进程。

4.1 项目准备

假设Django项目路径为/home/user/django_project,已安装Gunicorn和Celery:

pip install gunicorn celery

4.2 编写Supervisor配置文件

创建/etc/supervisor/conf.d/django_project.conf

[group:django_project]
programs=gunicorn,c celery_worker

[program:gunicorn]
; Gunicorn启动命令(绑定8000端口,4个工作进程)
command=/usr/bin/gunicorn --bind 0.0.0.0:8000 --workers 4 django_project.wsgi:application
directory=/home/user/django_project
user=user
autostart=true
autorestart=true
; 仅当 stderr 有输出时才记录日志
stderr_logfile=/home/user/django_project/gunicorn_error.log
stderr_logfile_maxbytes=20MB

[program:celery_worker]
; Celery Worker启动命令
command=/usr/bin/celery -A django_project worker --loglevel=info
directory=/home/user/django_project
user=user
autostart=true
autorestart=true
stdout_logfile=/home/user/django_project/celery_worker.log
stdout_logfile_maxbytes=20MB

4.3 启动并验证

# 加载配置
sudo supervisorctl reread
sudo supervisorctl update

# 查看状态
sudo supervisorctl status django_project:*

此时,Gunicorn已在8000端口启动Django服务,Celery Worker也已开始处理异步任务。若Gunicorn或Celery意外退出,Supervisor会自动重启它们,确保服务稳定运行。

4.4 日志查看与问题排查

若服务启动失败,可通过日志排查问题:

# 查看Gunicorn错误日志
cat /home/user/django_project/gunicorn_error.log

# 查看Celery日志
sudo supervisorctl tail -f django_project:celery_worker

五、相关资源

  • Pypi地址:https://pypi.org/project/supervisor/
  • Github地址:https://github.com/Supervisor/supervisor
  • 官方文档地址:https://supervisord.org/

关注我,每天分享一个实用的Python自动化工具。