你有没有过这样的经历:SSH 一断,用 nohup 跑起来的后端服务也随之消失;或者服务半夜崩了,第二天才发现接口早就不通了。Supervisor 是一个用 Python 写的进程管理工具,专门解决”后台进程怎么稳定跑、挂了怎么自动拉起、日志怎么收拢”这三件事。本文手把手教你用 Supervisor 守护后台服务,从安装、配置 program 段,到日志轮转与开机自启,把”手动重启”彻底变成历史。
一、为什么不用 nohup / systemd 就够了
先说清适用边界。systemd 是系统级服务管理器,适合托管单一、长期稳定的系统服务;而 Supervisor 胜在”轻量、跨发行版一致、对非 daemon 化的脚本/二进制极其友好”。很多自研程序、Python 爬虫、Node 服务并不会自己变成 daemon,用 systemd 写 unit 要处理一堆细节,而 Supervisor 一个 conf 文件就能让进程随崩随起。它还能在一个地方集中管理一组进程、统一看日志,这正是运维最想要的能力。如果你更偏好系统原生方案,也可以参考systemd 服务管理实战用 unit 文件托管。
二、安装与启动 Supervisor
# Debian / Ubuntu
sudo apt-get update && sudo apt-get install -y supervisor
# CentOS / Rocky(EPEL)
sudo yum install -y epel-release && sudo yum install -y supervisor
# 启动并设置开机自启(Supervisor 自身由 systemd 托管)
sudo systemctl enable --now supervisord
# 验证
supervisorctl status
安装后主配置文件在 /etc/supervisor/supervisord.conf,它默认会 include /etc/supervisor/conf.d/*.conf,所以我们把每个被守护的程序写成独立文件,互不干扰、便于版本管理。
三、编写一个 program 配置
假设我们有一个 Flask 后端 /opt/app/run.py,希望它常驻、崩溃自动重启。新建 /etc/supervisor/conf.d/app.conf:
[program:myapp]
command=/opt/app/venv/bin/python /opt/app/run.py
directory=/opt/app
user=appuser
autostart=true
autorestart=true
startretries=3
startsecs=5
stopwaitsecs=10
redirect_stderr=true
stdout_logfile=/var/log/supervisor/myapp.out.log
stdout_logfile_maxbytes=50MB
stdout_logfile_backups=10
environment=ENV="production",PORT="8000"
关键参数含义:autorestart=true 是灵魂——进程退出就拉起;startsecs=5 表示稳定运行 5 秒才算”启动成功”,避免启动即崩被误判;stopwaitsecs 给进程留出优雅退出的时间,和优雅停机(Graceful Shutdown)的思路一致,能减少中断期间的请求丢失。
四、常用管理命令
改完配置要让 Supervisor 重新加载。记住这组命令,日常 90% 的操作都在里面:
supervisorctl reread # 读取新增/修改的 conf
supervisorctl update # 应用变更(新增的会启动,删除的会停)
supervisorctl status # 查看所有进程状态
supervisorctl start myapp # 启动
supervisorctl stop myapp # 停止
supervisorctl restart myapp
supervisorctl tail -f myapp # 实时看日志,类似 tail -f
五、用 group 批量管理一组进程
当一个项目有多个配套进程(如 API + Worker + Beat),用 [group] 把它们绑成一组,一条命令统一启停:
[program:api]
command=/opt/app/venv/bin/python run_api.py
...
[program:worker]
command=/opt/app/venv/bin/python run_worker.py
...
[group:proj]
programs=api,worker
priority=999
之后 supervisorctl restart proj: 就能把整组一起重启,避免漏掉某个组件导致状态错乱。
六、核心指令速查表
| 指令 | 作用 | 推荐取值 |
|---|---|---|
| autorestart | 退出后是否自动拉起 | true(生产必开) |
| startsecs | 判定启动成功的稳定时长 | 3–10 秒 |
| startretries | 启动失败最大重试次数 | 3 |
| stopwaitsecs | 停止时等待优雅退出的时间 | 10 |
| stdout_logfile_maxbytes | 单个日志文件上限 | 50MB |
| stdout_logfile_backups | 日志轮转保留份数 | 10 |
七、日志轮转与排错
Supervisor 自带日志轮转(上面的 _maxbytes / _backups),不需要额外配 logrotate,这点比裸跑脚本省心。排错时优先级如下:① supervisorctl status 看 STATE,BACKOFF/FATAL 说明启动即退;② tail -f myapp 看标准输出里的报错;③ 确认 user 对该目录有读写权限、command 路径与虚拟环境绝对路径正确;④ 若端口被占,先 stop 再排查,避免僵尸进程占着端口。
八、配合 Nginx 对外暴露
Supervisor 只负责”让进程活着”,对外服务通常还要一层反向代理。例如让 Supervisor 托管一个 8000 端口的 Web 服务,再用 Nginx 反向代理把域名 80/443 转发过去,既拿到 HTTPS,又能做负载与限流。组合拳是:Supervisor 保活应用进程 + Nginx 做入口,二者职责清晰、互不替代。
九、生产落地 Checklist
上线前核对:① autorestart=true 且 startsecs 合理,避免”启动即崩→狂拉起”把 CPU 打满;② 日志路径放在独立分区或挂载,防止写满根盘(参考服务器安全加固里的磁盘与权限规范);③ 用专用低权限用户运行,不要 root;④ conf.d 文件纳入 Git,配置即代码;⑤ 把 supervisord 自身加入开机自启并监控其存活。做到这些,你的后台服务就真正”无人值守”了。
结语
Supervisor 不是什么黑科技,但它把”进程保活”这件小事做到了极致简单。对于一个需要长期运行的后台程序,花十分钟写好一个 conf,换来的可能是再也不用凌晨被”服务挂了”的告警叫醒。建议你在测试机上照本文把任意一个脚本托管起来,亲手执行一次 kill 再观察它是否被自动拉起——那一刻,你会真正理解进程守护的价值。




