Supervisor 进程管理
Supervisor 进程管理
简介
Supervisor 是一个用 Python 编写的进程管理工具,可以监控和控制类 UNIX 系统上的进程。它可以将普通的命令行进程变为守护进程(daemon),并在进程意外退出时自动重启。对于 .NET 应用部署在 Linux 环境中,Supervisor 是管理应用进程的常用方案,可以确保应用的高可用运行。
Supervisor 由两部分组成:supervisord(服务端守护进程)和 supervisorctl(命令行客户端)。supervisord 负责管理子进程的启停和监控,supervisorctl 提供命令行接口来与 supervisord 通信。
特点
优点
缺点
一、安装 Supervisor
yum 安装
# 安装 EPEL 源
yum install -y epel-release
# 安装 Supervisor
yum install -y supervisor
# 查看安装版本
supervisord --versionpip 安装
# 安装 Python pip
yum install -y python-pip
# 使用 pip 安装
pip install supervisor
# 验证安装
supervisord --version配置文件路径说明
| 文件/目录 | 说明 |
|---|---|
| /etc/supervisord.conf | 主配置文件 |
| /etc/supervisord.d/ | 子进程配置文件目录(推荐) |
| /var/log/supervisor/ | 默认日志目录 |
| /var/run/supervisor/ | 默认 PID 和 Socket 文件目录 |
二、主配置文件详解
主配置文件 /etc/supervisord.conf 包含了 supervisord 服务本身的全局配置。
# supervisord 主配置文件
[supervisord]
logfile=/var/log/supervisor/supervisord.log ; 主日志文件
logfile_maxbytes=50MB ; 日志文件最大大小
logfile_backups=10 ; 日志文件备份数量
loglevel=info ; 日志级别(critical/error/warn/info/debug/trace)
pidfile=/var/run/supervisord.pid ; PID 文件
nodaemon=false ; 是否前台运行
minfds=1024 ; 最小文件描述符数
minprocs=200 ; 最小进程数
[supervisorctl]
serverurl=unix:///var/run/supervisor/supervisor.sock ; 连接 supervisord 的地址
[unix_http_server]
file=/var/run/supervisor/supervisor.sock ; Socket 文件路径
chmod=0700 ; Socket 文件权限
;[inet_http_server]
;port=0.0.0.0:9001 ; Web UI 和 XML-RPC 监听端口
;username=user ; 认证用户名
;password=123 ; 认证密码
[rpcinterface:supervisor]
supervisor.rpcinterface_factory=supervisor.rpcinterface:make_main_rpcinterface
[include]
files = supervisord.d/*.ini ; 包含子进程配置文件注意事项
三、Program 配置详解
每个需要管理的进程都通过一个独立的 program 配置段来定义,配置文件放在 /etc/supervisord.d/ 目录下。
配置文件模板
[program:myapp]
; 基本配置
command=dotnet MyApp.dll --urls http://*:5000 ; 启动命令(必须前台运行)
directory=/var/www/myapp ; 工作目录
user=www-data ; 运行用户
numprocs=1 ; 启动进程实例数
process_name=%(program_name)s_%(process_num)02d ; 进程名模板(多实例时有用)
; 自动重启配置
autostart=true ; supervisord 启动时自动启动
autorestart=true ; 进程退出后自动重启
startsecs=3 ; 启动多少秒后认为启动成功
startretries=3 ; 启动重试次数
exitcodes=0,2 ; 退出码,触发自动重启
stopsignal=TERM ; 停止信号
stopwaitsecs=10 ; 等待停止的最大秒数
stopasgroup=false ; 是否停止整个进程组
killasgroup=false ; 是否强制终止整个进程组
; 日志配置
stdout_logfile=/var/log/myapp/stdout.log ; 标准输出日志
stdout_logfile_maxbytes=2MB ; 单个日志文件最大大小
stdout_logfile_backups=10 ; 日志文件备份数量
stdout_capture_maxbytes=1MB ; 捕获管道最大字节数
stdout_events_enabled=false ; 是否发送事件
stderr_logfile=/var/log/myapp/stderr.log ; 标准错误日志
stderr_logfile_maxbytes=2MB ; 错误日志最大大小
stderr_logfile_backups=10 ; 错误日志备份数量
; 环境变量
environment=ASPNETCORE_ENVIRONMENT="Production",DOTNET_SYSTEM_GLOBALIZATION_INVARIANT="1"
; 优先级
priority=999 ; 启动/关闭优先级(值越小越优先启动)核心参数说明
| 参数 | 说明 | 推荐值 |
|---|---|---|
| command | 启动命令,必须为前台运行模式 | 根据应用确定 |
| autostart | supervisord 启动时是否自动启动 | true |
| autorestart | 进程退出后是否自动重启 | true/unexpected |
| startsecs | 启动成功判定时间 | 3-10 秒 |
| startretries | 启动失败重试次数 | 3-5 次 |
| stopsignal | 停止进程使用的信号 | TERM(.NET 应用推荐) |
| stopwaitsecs | 停止超时时间 | 10-30 秒 |
autorestart 三种模式
| 模式 | 说明 |
|---|---|
| true | 进程退出后始终自动重启 |
| false | 进程退出后不自动重启 |
| unexpected | 仅当退出码不在 exitcodes 中时自动重启 |
四、.NET 应用配置示例
单实例 .NET Web API
[program:myapi]
command=dotnet MyApi.dll --urls http://*:5000
directory=/var/www/myapi/publish/
autostart=true
autorestart=true
startsecs=5
startretries=3
stopsignal=TERM
stopwaitsecs=15
stdout_logfile=/var/log/myapi/stdout.log
stdout_logfile_maxbytes=5MB
stdout_logfile_backups=10
stderr_logfile=/var/log/myapi/stderr.log
stderr_logfile_maxbytes=5MB
stderr_logfile_backups=10
user=www-data
environment=ASPNETCORE_ENVIRONMENT="Production",ASPNETCORE_URLS="http://*:5000"
priority=100多实例 .NET 应用(多进程负载)
[program:myweb]
command=dotnet MyWeb.dll --urls http://*:%(process_num)80
directory=/var/www/myweb/publish/
autostart=true
autorestart=true
startsecs=3
startretries=3
numprocs=4
process_name=%(program_name)s_%(process_num)02d
stdout_logfile=/var/log/myweb/stdout_%(process_num)02d.log
stdout_logfile_maxbytes=2MB
stderr_logfile=/var/log/myweb/stderr_%(process_num)02d.log
stderr_logfile_maxbytes=2MB
user=www-data
priority=100以上配置会启动 4 个进程:myweb_00(端口 8080)、myweb_01(端口 8180)、myweb_02(端口 8280)、myweb_03(端口 8380),配合 Nginx 负载均衡使用。
.NET Worker Service(后台服务)
[program:orderworker]
command=dotnet OrderWorker.dll
directory=/var/www/orderworker/publish/
autostart=true
autorestart=true
startsecs=5
startretries=5
stopsignal=TERM
stopwaitsecs=30
stdout_logfile=/var/log/orderworker/stdout.log
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=20
stderr_logfile=/var/log/orderworker/stderr.log
stderr_logfile_maxbytes=10MB
stderr_logfile_backups=20
user=www-data
environment=DOTNET_ENVIRONMENT="Production"
priority=200五、supervisorctl 命令详解
服务管理
# 启动 Supervisor 服务
supervisord -c /etc/supervisord.conf
# 停止 Supervisor 服务(会停止所有管理的进程)
supervisorctl shutdown
# 重新加载配置
supervisorctl reload
# 更新配置(仅重启变更的进程)
supervisorctl update
# 重载配置文件(检测新增配置)
supervisorctl reread进程管理
# 查看所有进程状态
supervisorctl status
# 查看指定进程状态
supervisorctl status myapi
# 启动指定进程
supervisorctl start myapi
# 停止指定进程
supervisorctl stop myapi
# 重启指定进程
supervisorctl restart myapi
# 启动所有进程
supervisorctl start all
# 停止所有进程
supervisorctl stop all
# 重启所有进程
supervisorctl restart all
# 启动指定组的所有进程
supervisorctl start mygroup:*
# 清除进程的日志
supervisorctl clear myapi
# 清除所有日志
supervisorctl clear all配置更新流程
# 步骤1:创建或修改配置文件
vi /etc/supervisord.d/newapp.ini
# 步骤2:重新读取配置
supervisorctl reread
# 步骤3:更新并启动新进程
supervisorctl update
# 如果只启动特定任务
supervisorctl update newapp六、进程组管理
可以将多个进程组织到一个组中,方便批量管理。
[group:myapps]
programs=myapi,orderworker,backgroundservice
priority=50# 启动整个组
supervisorctl start myapps:*
# 停止整个组
supervisorctl stop myapps:*
# 重启整个组
supervisorctl restart myapps:*
# 查看组内进程状态
supervisorctl status myapps:*七、Web UI 管理
Supervisor 提供了一个简单的 Web 管理界面,可以在浏览器中查看和管理进程。
开启 Web UI
编辑主配置文件,取消注释 inet_http_server 段:
[inet_http_server]
port=0.0.0.0:9001 ; 监听地址和端口
username=admin ; 用户名
password=your_password ; 密码# 重启 Supervisor
supervisorctl reload
# 防火墙开放端口
firewall-cmd --add-port=9001/tcp --permanent
firewall-cmd --reload访问 http://服务器IP:9001 即可看到 Web 管理界面,可以进行进程的启停、重启、查看日志等操作。
安全建议
八、事件监听(Event Listeners)
Supervisor 支持事件监听机制,可以在进程状态变化时执行自定义操作。
进程状态监控事件监听器示例
[eventlistener:crashmail]
command=/usr/local/bin/crashmail.sh
events=PROCESS_STATE_EXITED
autostart=true
autorestart=true
stderr_logfile=/var/log/supervisor/crashmail_err.log
stdout_logfile=/var/log/supervisor/crashmail_out.log邮件通知脚本示例
#!/bin/bash
# /usr/local/bin/crashmail.sh
while read line; do
echo $line
# 读取 header
read header
# 读取 payload
read payload
# 解析进程名
process_name=$(echo $payload | sed 's/.*processname:\([^ ]*\).*/\1/')
# 解析退出状态
from_state=$(echo $payload | sed 's/.*from_state:\([^ ]*\).*/\1/')
# 发送邮件通知
echo "进程 $process_name 从 $from_state 状态退出" | \
mail -s "Supervisor 进程异常退出" admin@example.com
echo "RESULT 2"
echo "OK"
done九、配置 systemd 开机启动
确保 supervisord 本身在系统启动时自动运行,使用 systemd 服务管理。
# 创建 systemd 服务文件
vi /usr/lib/systemd/system/supervisord.service[Unit]
Description=Supervisor daemon
Documentation=http://supervisord.org
After=network.target
[Service]
Type=forking
ExecStart=/usr/bin/supervisord -c /etc/supervisord.conf
ExecStop=/usr/bin/supervisorctl shutdown
ExecReload=/usr/bin/supervisorctl reload
KillMode=process
Restart=on-failure
RestartSec=42s
[Install]
WantedBy=multi-user.target# 重新加载 systemd 配置
systemctl daemon-reload
# 设置开机启动
systemctl enable supervisord
# 启动服务
systemctl start supervisord
# 查看服务状态
systemctl status supervisord
# 验证是否开机启动
systemctl is-enabled supervisord十、Nginx + Supervisor + .NET 典型部署
架构说明
Nginx 作为反向代理处理静态文件和 HTTPS,Supervisor 管理 .NET 应用进程,两者配合实现高可用的 .NET Web 应用部署。
Nginx 反向代理配置
upstream myapi_backend {
server 127.0.0.1:5000;
# 如果多实例
# server 127.0.0.1:5080;
# server 127.0.0.1:5180;
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://myapi_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 30s;
proxy_read_timeout 120s;
proxy_send_timeout 30s;
}
}部署流程
# 1. 发布 .NET 应用
dotnet publish -c Release -o /var/www/myapi/publish
# 2. 创建日志目录
mkdir -p /var/log/myapi
# 3. 创建 Supervisor 配置
cat > /etc/supervisord.d/myapi.ini << 'EOF'
[program:myapi]
command=dotnet MyApi.dll --urls http://*:5000
directory=/var/www/myapi/publish/
autostart=true
autorestart=true
startsecs=5
startretries=3
stopsignal=TERM
stopwaitsecs=15
stdout_logfile=/var/log/myapi/stdout.log
stdout_logfile_maxbytes=5MB
stderr_logfile=/var/log/myapi/stderr.log
stderr_logfile_maxbytes=5MB
user=www-data
environment=ASPNETCORE_ENVIRONMENT="Production"
EOF
# 4. 更新并启动
supervisorctl reread
supervisorctl update
# 5. 验证进程状态
supervisorctl status myapi
# 6. 重启 Nginx
nginx -t && nginx -s reload应用更新流程
# 1. 发布新版本
dotnet publish -c Release -o /var/www/myapi/publish
# 2. 重启应用(Supervisor 会自动重启进程)
supervisorctl restart myapi
# 3. 查看日志确认启动成功
supervisorctl tail -f myapi stdout
# 4. 如果有问题,回滚(恢复旧版本后重启)
supervisorctl restart myapi十一、日志管理
日志轮转配置
Supervisor 内置了日志轮转功能,通过 stdout_logfile_maxbytes 和 stdout_logfile_backups 参数控制。
使用 logrotate 管理日志
# 创建 logrotate 配置
cat > /etc/logrotate.d/supervisor << 'EOF'
/var/log/supervisor/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
copytruncate
}
EOF
# 为应用日志也配置轮转
cat > /etc/logrotate.d/myapp << 'EOF'
/var/log/myapi/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
copytruncate
}
EOF实时查看日志
# 查看 stdout 日志
supervisorctl tail myapi stdout
# 查看 stderr 日志
supervisorctl tail myapi stderr
# 持续查看日志
supervisorctl tail -f myapi stdout
# 查看最后 1000 字符
supervisorctl tail -1000 myapi stdout十二、常见问题排查
# 问题1:进程启动后立即退出
# 查看错误日志
supervisorctl tail myapi stderr
# 常见原因:
# - command 路径不对
# - directory 目录不存在
# - 用户权限不足
# - .NET 运行时缺失
# 问题2:进程反复重启
# 检查 startsecs 是否设置过短
# 查看日志确认是否启动成功
supervisorctl tail myapi stdout
# 问题3:无法连接 supervisord
# 检查 supervisord 是否运行
systemctl status supervisord
# 检查 socket 文件是否存在
ls -la /var/run/supervisor/supervisor.sock
# 问题4:更新配置后不生效
supervisorctl reread
supervisorctl update
# 问题5:权限问题
# 确保运行用户有权限访问工作目录和日志目录
chown -R www-data:www-data /var/www/myapp
chown -R www-data:www-data /var/log/myapp总结
Supervisor 是轻量级进程管理工具,适合守护 .NET、Python 等应用。核心功能:自动重启、日志管理、Web 管理。生产环境建议配合 systemd 使用。
关键知识点
- 部署类主题的核心不是“装成功”,而是“稳定运行、可排障、可回滚”。
- 同一个服务通常至少要关注版本、目录、端口、权限、数据、日志和备份。
- Linux 问题经常跨越系统层、网络层、服务层和应用层。
项目落地视角
- 把安装步骤补成可重复执行的清单,必要时写成脚本或配置文件。
- 把配置目录、数据目录、日志目录和挂载点明确拆开。
- 上线前检查防火墙、SELinux、时区、磁盘、系统服务和健康检查。
常见误区
- 使用 latest 或未固定版本,导致环境不可复现。
- 只验证启动成功,不验证持久化、开机自启和故障恢复。
- 遇到问题先改配置而不是先看日志和依赖链路。
进阶路线
- 继续补齐 systemd、性能监控、安全加固和备份恢复。
- 把单机操作升级成 Docker、Kubernetes 或 IaC 方案。
- 建立标准化运维手册,包括巡检、扩容、回滚和灾备演练。
适用场景
- 当你准备把《Supervisor 进程管理》真正落到项目里时,最适合先在一个独立模块或最小样例里验证关键路径。
- 适合单机环境初始化、中间件快速搭建、测试环境验证和生产部署前准备。
- 当服务稳定性依赖端口、权限、目录、网络和系统参数时,这类主题会直接影响成败。
落地建议
- 固定版本号与镜像标签,避免“latest”带来的不可预期变化。
- 把配置、数据、日志目录拆开管理,并记录恢复步骤。
- 上线前确认端口、防火墙、SELinux、时区和磁盘空间。
排错清单
- 先查 systemctl、容器日志和应用日志,确认失败发生在哪一层。
- 检查端口占用、目录权限、挂载路径和网络连通性。
- 如果是新环境问题,优先对比与已知正常环境的差异。
复盘问题
- 如果把《Supervisor 进程管理》放进你的当前项目,最先要验证的输入、输出和失败路径分别是什么?
- 《Supervisor 进程管理》最容易在什么规模、什么边界条件下暴露问题?你会用什么指标或日志去确认?
- 相比默认实现或替代方案,采用《Supervisor 进程管理》最大的收益和代价分别是什么?
