失踪人口回归:Supervisor时隔三年再更新 时隔近三年,这款经典的进程管理工具终于迎来了更新。
最近偶然注意到Supervisor项目发布了新版本(4.3.0—2025.08.23),印象中这个项目已经很久没有动静了。于是特意去翻看了更新日志,才发现距离上个版本发布已经过去了两年零八个月。仔细阅读版本说明后,发现这次更新主要集中在性能优化和稳定性提升,主要包括了:
两项重要Bug修复:
CPU 使用率优化:修复了在某些情况下轮询器未注销已关闭的文件描述符,导致过度轮询、CPU 占用异常升高的问题。
重启稳定性提升:修复了在重启期间若有 HTTP 请求可能导致“端口已被占用”错误的问题。
兼容性更新
支持 Python 3.13:修复了仅在 Python 3.13 环境下会失败的单元测试。
清理依赖关系:Python 3.8 及以上版本不再需要 setuptools 作为运行时依赖;Python 3.7 及以下版本仍需手动安装 setuptools。
时间飞逝,Supervisor已有近三年未发布版本了,而我也差不多有三年多没有使用这个组件了。正好借此机会,我将之前在使用过程中记录的笔记重新整理了一遍,分享给大家。
初识Supervisor:你的进程管理 Supervisor是用Python开发的一款用于Linux的进程管理工具,采用典型的C/S架构,够高效监控和管理进程状态。官方资源:Github仓库 、官方文档
Supervisor主要包含两个组件:
主要特点:
进程状态监控和管理
进程崩溃自动重启
统一的进程管理接口
Web管理界面支持
进程组管理功能
注意事项:
Supervisor要求要离的程序必须非守护进程方式运行(例如:管理nginx,必须在 nginx 的配置文件里添加一行设置 daemon off 让 nginx 以非 daemon 方式启动)
修改配置文件(配置文件通常位于/etc/supervisord.conf
)后需要执行reload才能更改生效。
快速上手:你只需要几分钟 安装 1 2 3 4 pip install supervisor echo_supervisord_conf > /etc/supervisord.conf
常用命令
1 2 3 4 5 supervisord -c /etc/supervisord.conf ps aux | grep supervisord
1 2 3 4 5 6 supervisorctl status supervisorctl start program_name supervisorctl stop program_name supervisorctl restart program_name supervisorctl reread supervisorctl update
1 2 3 4 5 6 7 8 9 supervisorctl > status > start program_name > stop program_name > restart program_name > reread > update > start fastapi:* > stop fastapi:*
基础使用:
step1:编辑supervisor主配置文件,在配置文件的末尾加上[include]内容
1 2 3 ... [include] files=/etc/supervisor.d/*.conf
step2:创建应用配置文件:/etc/supervisor.d/demo.conf
配置文件
1 2 3 4 5 6 7 8 9 [program:自定义的服务名称] command =python3 /xxxx/main.py directory=/xxxx process_name=%(program_name)s autorestart=true startsecs=3 stdout_logfile=/home/task.log stderr_logfile=/home/task.log user=your_username
1 supervisord -c /etc/supervisor.conf
配置详解:磨刀不误砍柴工
打开配置文件: /etc/supervisord.conf
基础配置段 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 [unix_http_server] file=/var/run/supervisor.sock ; socket文件路径 ;chmod =0700 ;socket文件的mode,默认是0700 ;chown =nobody:nogroup ;socket文件的owner,格式:uid:gid [inet_http_server] ;HTTP服务器,提供web管理界面 port=0.0.0.0:9001 ;Web管理后台运行的IP和端口,如果开放到公网,需要注意安全性 username=user ;登录管理后台的用户名 password=pwd ;登录管理后台的密码 [supervisord] logfile=/tmp/supervisord.log ;日志文件,默认是 $CWD /supervisord.log logfile_maxbytes=50MB ;日志文件大小,超出会rotate,默认 50MB,如果设成0,表示不限制大小 logfile_backups=10 ;日志文件保留备份数量默认10,设为0表示不备份 loglevel=info ;日志级别,默认info,其它: debug,warn,trace pidfile=/tmp/supervisord.pid ;pid 文件 nodaemon=false ;是否在前台启动,默认是false ,即以 daemon 的方式启动 minfds=1024 ;可以打开的文件描述符的最小值,默认 1024 minprocs=200 ;可以打开的进程数的最小值,默认 200 [supervisorctl] serverurl=unix:///tmp/supervisor.sock ;通过UNIX socket连接supervisord,路径与unix_http_server部分的file一致 ;serverurl=http://127.0.0.1:9001 ; 通过HTTP的方式连接supervisord [include] files=/etc/supervisor.d/*.conf
程序配置段 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [program:your_program_name] command =/path/to/your/command ; 必须:要执行的命令process_name=%(program_name)s ; 进程名 numprocs=1 ; 进程数量 directory=/path/to/run/in ; 执行命令前切换的目录 autostart=true ; 是否随supervisor启动 autorestart=unexpected ; 退出时是否自动重启 startsecs=1 ; 启动后持续运行1秒才认为是成功 startretries=3 ; 启动失败时的重试次数 user=username ; 运行用户 redirect_stderr=true ; 重定向stderr到stdout stdout_logfile=/path/to/logfile ; stdout日志路径 stdout_logfile_maxbytes=1MB ; 日志文件最大大小 stdout_logfile_backups=10 ; 日志备份数量 environment=KEY="value" ; 环境变量
入门到进阶:让效率翻倍 Web管理界面 启动Web管理界面可以直观地监控和管理进程, 在/etc/supervisord.conf中修改[inet_http_server]的参数下列参数,修改后记得重启supervisor进程,在浏览器访问 http://<host-ip>:9001
1 2 3 4 [inet_http_server] port=0.0.0.0:9001 username=your_username password=your_password
进程分组管理 对于多个相关进程,可以使用分组功能进行统一管理:
1 2 3 4 5 6 7 8 9 10 11 [group:app_group] programs=app1,app2,app3 [program:app1] command =/path/to/app1[program:app2] command =/path/to/app2[program:app3] command =/path/to/app3
分组后可以使用下列命令进行管理整个组:
1 2 supervisorctl start app_group: supervisorctl stop app_group:
需要注意的是:
当添加了上述配置后,app1、app2和app3 的进程名就会变成 app_group:app1 、 app_group:app2和app_group:app1 ,以后就要用这个名字来管理进程了,而不是之前的 app[x]了。
Supervisor配置开机启动 方式一:
centos-7
进入 / lib/systemd/system 目录,并创建 supervisord.service 文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [Unit] Description=supervisord After=network.target [Service] Type=forking ExecStart=/usr/bin/supervisord -c /etc/supervisor/supervisord.conf ExecStop=/usr/bin/supervisorctl $OPTIONS shutdown ExecReload=/usr/bin/supervisorctl $OPTIONS reload KillMode=process Restart=on-failure RestartSec=42s [Install] WantedBy=multi-user.target
1 2 systemctl enable supervisord systemctl start supervisord
方式二
Linux环境中:以systemd的方式管理
编写启动脚本:vim /etc/rc.d/init.d/supervisord
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 51 52 53 54 55 56 57 58 59 60 61 62 #!/bin/sh . /etc/rc.d/init.d/functions prog="supervisord" prefix="/usr" exec_prefix="${prefix} " prog_bin="${exec_prefix} /bin/supervisord" PIDFILE="/var/run/$prog .pid" start (){ echo -n $"Starting $prog : " daemon $prog_bin --pidfile $PIDFILE -c /etc/supervisord.conf [ -f $PIDFILE ] && success $"$prog startup" || failure $"$prog startup" echo } stop (){ echo -n $"Shutting down $prog : " [ -f $PIDFILE ] && killproc $prog || success $"$prog shutdown" echo } case "$1 " in start) start ;; stop) stop ;; status) status $prog ;; restart) stop start ;; *) echo "Usage: $0 {start|stop|restart|status}" ;; esac
1 2 3 4 sudo chmod +x /etc/rc.d/init.d/supervisordsudo chkconfig --add supervisordsudo chkconfig supervisord onsudo service supervisord start
实践出真知 Django应用配置 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 [program:django] directory=/root/social_engineering/ command =/root/anaconda3/bin/python manage.py runserver 0.0.0.0:8000 autostart=true autorestart=true startsecs=1 stderr_logfile=/tmp/django_stderr.log stdout_logfile=/tmp/django_stdout.log redirect_stderr = true stdout_logfile_maxbytes = 20 stdout_logfile_backups = 20 ; 可以通过 environment 来添加需要的环境变量,一种常见的用法是修改 PYTHONPATH ; environment=PYTHONPATH=$PYTHONPATH :/path/to/somewhere
Celery应用配置 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 [program:celery] directory=/root/social_engineering/ command =/root/anaconda3/bin/celery -A tasks worker --loglevel=infoautostart=true autorestart=true startsecs=1 stderr_logfile=/tmp/celery_stderr.log stdout_logfile=/tmp/celery_stdout.log redirect_stderr = true stdout_logfile_maxbytes = 20 stdout_logfile_backups = 20
Redis服务配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [program:zedis] command =/opt/zedis/redis-server /opt/zedis/redis.confuser=redisuser autostart=true ;启动supervisord的时候会将该配置项设置为true 的所有进程自动启动 stopasgroup=true ;使用supervisorctl停止zedis时,子进程也会一起停止 killasgroup=true ;向进程组发送kill 信号,包括子进程 startsecs=10 ;进程从STARING状态转换到RUNNING状态所需要保持运行10s时间 startretries=3 ;启动失败自动重试次数,默认是3 autorestart=true ;进程停止后自动启动 stdout_logfile=/var/log/zedis-out stdout_logfile_maxbytes=1MB stdout_logfile_backups=10 stderr_logfile=/var/log/zedis-err stderr_logfile_maxbytes=1MB stderr_logfile_backups=10
Ø 因为无法监视后台进程,需要把Zedis前台运行(daemonize no),否则会识别不到Zedis启动,重试启动3次,日志提示6379已占用。
Ø 因为redis.conf指定了logfile,stdout_logfile并无内容输出;如果不指定redis.conf只是启动redis-server,日志会输出到stdout_logfile。
组应用配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 [group:fastapi] programs=fastapi-app [program:fastapi-1] command =/home/python/scripts/fastapi1_app.shdirectory=/home/python/fastapi-1-backend user=python autorestart=true redirect_stderr=false loglevel=info stopsignal=KILL stopasgroup=true killasgroup=true [program:fastapi-2] command =/home/python/scripts/fastapi-2.shdirectory=/home/python/fastapi-2-backend user=python autorestart=true redirect_stderr=false loglevel=info stopsignal=KILL stopasgroup=true killasgroup=true
避坑指南 问题1:sock文件不存在 问题描述 :unix:///tmp/supervisor.sock no such file
**根源分析:**在supervisor默认配置中,其启动的sock等都会放到tmp目录,而tmp目录会自动清理导致无法使用supervisorctl
解决方案 :
1 2 3 4 5 6 7 8 9 sed -i 's|/tmp/supervisor|/var/run/supervisor|g' /etc/supervisord.conf mkdir -p /var/run/supervisorchmod 755 /var/run/supervisorsupervisorctl reload
问题2:进程不断重启 问题描述 :进程启动后Supervisor不断尝试重启
解决方案 :
确保管理的进程以前台方式运行
检查进程启动命令是否正确
查看日志文件定位具体问题
问题3:启动了多个supervisord服务,导致无法正常关闭服务 问题描述 :在运行supervisord -c /etc/supervisord.conf
之前,直接运行过``supervisord -c /etc/supervisord.d/xx.conf`导致有些进程被多个superviord管理,无法正常关闭进程
解决方案 :
使用ps -fe | grep supervisord
查看所有启动过的supervisord服务,kill相关的进程。
总结一下 Supervisor是一款强大且灵活的进程管理工具,合理配置显著提升服务的稳定性和可维护性。本文从安装配置、基础使用到进阶使用全面介绍了Supervisor的使用方法, 希望能帮助你在实际工作中更好地运用这一工具。
最佳实践建议:
为每个服务创建独立的配置文件
合理配置日志轮转,避免磁盘空间不足
使用Web界面进行日常监控和管理
设置进程分组,简化管理操作
配置开机启动,确保服务可靠性