给 Nginx 装个 “守护保镖”——Supervisor 配置折腾记

2025-10-0216:27:46 评论 100

前段时间服务器上的 Nginx 总出幺蛾子:主进程时不时就崩,每次都得手动重启才能恢复服务。虽说临时重启能解决问题,但总不能一直盯着,趁着今天有空,干脆彻底把这个隐患解决掉。

先查了 Nginx 崩溃的原因,看日志和系统监控,大概率是内存溢出导致的 —— 于是先调整了 Nginx 的配置(比如优化 worker 进程数、调整连接数限制),至于能不能根治还得再观察。但光靠改配置不够,万一再崩了还是得手动处理,索性决定装个 Supervisor 做监控,让它接管 Nginx 的启停:只要 Nginx 进程退出,Supervisor 就自动重启,彻底解放双手。

不过折腾的过程比预想中曲折。我的 Nginx 和 Supervisor 都是通过服务器面板装的,第一步就踩了坑 —— 得先把 Nginx 自带的自启动关掉,再把 Supervisor 的自启动打开,不然两者会 “抢着管” Nginx,导致进程混乱。

接下来的问题更具体:清理旧进程时,总有残留的 Nginx 进程杀不干净;端口也时不时被占用,导致新的 Nginx 进程启动失败;一开始想通过中间脚本(比如 nginx_manage.sh)来处理清场和启动,结果又遇到各种报错…… 前前后后试了好几种方案,比如把多行命令压缩成单行、彻底删除 Supervisor 残留的配置文件、注释掉多余的 [include] 加载项,才算把所有问题理顺。

最终看着两种崩溃场景(主进程单独崩、全进程被杀死)都能被 Supervisor 自动恢复,才算松了口气。把整个过程记下来,既是给自己留个笔记,也希望能给遇到类似问题的朋友做个参考 —— 毕竟折腾过的坑,能少一个是一个。

Supervisor 守护 Nginx 全流程总结

一、环境信息

组件 路径 / 版本 说明
Supervisor 配置路径:/xp/server/supervisor/supervisord.conf 面板安装(非 systemd 管理,通过进程检测状态)
Nginx 启动路径:/xp/server/nginx/sbin/nginx 需守护的 Web 服务,依赖 80/443/888 端口
关键端口 80(HTTP)、443(HTTPS)、888(面板) 需避免残留进程占用,否则 Nginx 启动失败
日志路径 /xp/server/supervisor/log/ 存放 Supervisor 主日志(supervisord.log)和 Nginx 运行日志(nginx.out.log)

二、核心问题与排查思路

1. 问题 1:Supervisor 配置解析报错

  • 现象:启动 Supervisor 时提示语法错误,指向 [program:nginx] 的 command 行
  • 原因:command 用多行写法,未正确闭合引号,Supervisor 无法识别换行符
  • 解决:将多行命令用 ; 压缩为单行,确保引号完整

2. 问题 2:Nginx 启动报 FATAL Exited too quickly

  • 现象:Supervisor 显示 Nginx 启动后立即退出,日志提示 bind() to 0.0.0.0:80 failed (98: Address already in use)
  • 原因:80/443/888 端口被残留进程(旧 Nginx 或其他服务)占用,清理不彻底
  • 解决:用 netstat 杀端口占用 + killall -9 nginx 补杀残留

3. 问题 3:提示 can't find command '/usr/local/bin/nginx_manage.sh'

  • 现象:Supervisor 启动后 Nginx 状态为 FATAL,日志找不到旧脚本
  • 原因:[include] 目录(/xp/server/supervisor/conf.d/)有残留配置,仍调用已删除的旧脚本
  • 解决:删除 conf.d/ 下所有文件,或注释主配置中的 [include] 指令

4. 问题 4:systemctl status supervisord 检测不到进程

  • 现象:systemd 命令显示 Supervisor 为 inactive (dead),但 Nginx 能正常运行
  • 原因:Supervisor 由面板安装,用自定义进程管理(非 systemd 服务)
  • 解决:用 pgrep -f "supervisord" 直接检测进程,或 supervisorctl status 验证管理状态

三、完整操作步骤(含命令)

步骤 1:清理旧环境(避免残留干扰)

# 1. 强制杀死所有 Supervisor 和 Nginx 进程
pkill -9 supervisord
pkill -9 nginx
killall -9 nginx 2>/dev/null # 屏蔽“无进程可杀”的报错
# 2. 清理 80/443/888 端口占用(即使非 Nginx 占用也强制杀)
netstat -tunlp | grep -E ':80|:443|:888' | awk '{print $7}' | cut -d'/' -f1 | sort -u | xargs -I {} kill -9 {} 2>/dev/null
# 3. 验证清理结果(无输出即成功)
echo "=== 清理验证 ==="
pgrep supervisord && echo "❌ 残留 Supervisor 进程" || echo "✅ Supervisor 已清理"
pgrep nginx && echo "❌ 残留 Nginx 进程" || echo "✅ Nginx 已清理"
netstat -tunlp | grep -E ':80|:443|:888' && echo "❌ 端口仍被占用" || echo "✅ 端口已释放"

步骤 2:编辑 Supervisor 核心配置

2.1 打开配置文件

vim /xp/server/supervisor/supervisord.conf

2.2 完整配置

按 i 进入 vim 编辑模式,粘贴以下内容,按 Esc 退出编辑:

[inet_http_server]
port=127.0.0.1:9001 # 仅本地访问,安全优先
[supervisord]
logfile=/xp/server/supervisor/log/supervisord.log
logfile_maxbytes=50MB
logfile_backups=10
loglevel=info
pidfile=/xp/server/supervisor/supervisord.pid
nodaemon=false # 后台运行(默认正确)
minfds=1024
minprocs=200
user=root # root 权限确保杀进程/启动无问题
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///xp/server/supervisor/supervisor.sock
# 核心:Nginx 监控配置(单行命令,清场+启动一体化)
[program:nginx]
command=/bin/bash -c "netstat -tunlp | grep -E ':80|:443|:888' | awk '{print $7}' | cut -d'/' -f1 | sort -u | xargs -I {} kill -9 {} 2>/dev/null; sleep 2; ps -ef | grep -i nginx | grep -v grep | awk '{print $2}' | xargs -I {} kill -9 {} 2>/dev/null; sleep 2; /xp/server/nginx/sbin/nginx -g 'daemon off;'"
autostart=true # Supervisor 启动时自动启动 Nginx
autorestart=true # Nginx 崩溃时自动重启(核心守护)
startretries=3 # 启动失败重试 3 次
startsecs=10 # 稳定运行 10 秒算启动成功
stopwaitsecs=10 # 停止时等待 10 秒再强制杀
user=root
redirect_stderr=true # 错误日志重定向到 stdout_logfile
stdout_logfile=/xp/server/supervisor/log/nginx.out.log
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=5
stopasgroup=true # 停止时连带杀子进程(worker)
killasgroup=true # 强制杀整个进程组
# 注释 include(避免加载残留配置)
;[include]
;files = /xp/server/supervisor/conf.d/*.conf

2.3 保存退出 vim

按 Esc 后,输入 :wq 并回车(wq = 保存并退出;若放弃修改输入 :q! 强制退出)

步骤 3:启动 Supervisor 并验证初始状态

# 1. 启动 Supervisor(加载新配置)
/xp/server/supervisor/supervisord -c /xp/server/supervisor/supervisord.conf
# 2. 等待 15 秒(给“清场+启动”命令执行时间)
sleep 15
# 3. 验证 Supervisor 进程
pgrep -f "supervisord" && echo "✅ Supervisor 启动成功" || echo "❌ Supervisor 启动失败"
# 4. 验证 Nginx 状态(需显示 RUNNING)
sudo /xp/server/supervisor/supervisorctl status nginx

步骤 4:验证两种崩溃场景(核心测试)

场景 1:Nginx 主进程单独崩溃

# 1. 记录当前主进程 PID
INITIAL_MASTER_PID=$(pgrep -f "nginx: master process")
echo "当前 Nginx 主 PID:$INITIAL_MASTER_PID"
# 2. 杀死主进程(模拟崩溃)
kill -9 $INITIAL_MASTER_PID
echo "已杀死主进程(PID:$INITIAL_MASTER_PID)"
# 3. 等待 15 秒(Supervisor 自动重启)
sleep 15
# 4. 验证结果
NEW_MASTER_PID1=$(pgrep -f "nginx: master process")
SUP_STATUS1=$(sudo /xp/server/supervisor/supervisorctl status nginx | awk '{print $2}')
echo -e "\n=== 场景1结果 ==="
[ -n "$NEW_MASTER_PID1" ] && [ "$NEW_MASTER_PID1" != "$INITIAL_MASTER_PID" ] && echo "✅ 主进程自动重启成功(新 PID:$NEW_MASTER_PID1)" || echo "❌ 失败"
[ "$SUP_STATUS1" = "RUNNING" ] && echo "✅ Supervisor 守护正常" || echo "❌ 异常"

场景 2:Nginx 所有进程被杀死

# 1. 杀死所有 Nginx 进程(主进程+子进程)
pkill -9 nginx
killall -9 nginx 2>/dev/null
echo "已杀死所有 Nginx 进程"
# 2. 等待 15 秒
sleep 15
# 3. 验证结果
NEW_MASTER_PID2=$(pgrep -f "nginx: master process")
SUP_STATUS2=$(sudo /xp/server/supervisor/supervisorctl status nginx | awk '{print $2}')
PORT_CHECK=$(netstat -tunlp | grep -E ':80|:443|:888' | grep nginx | wc -l)
echo -e "\n=== 场景2结果 ==="
[ -n "$NEW_MASTER_PID2" ] && [ "$NEW_MASTER_PID2" != "$NEW_MASTER_PID1" ] && echo "✅ 所有进程自动重启成功(新 PID:$NEW_MASTER_PID2)" || echo "❌ 失败"
[ "$SUP_STATUS2" = "RUNNING" ] && echo "✅ Supervisor 守护正常" || echo "❌ 异常"
[ "$PORT_CHECK" -ge 1 ] && echo "✅ 端口重新绑定成功" || echo "❌ 端口未绑定"

步骤 5:服务器重启后验证(确保开机自启)

# 1. 重启服务器
reboot
# 2. 重启后登录,验证 Supervisor 进程
pgrep -f "supervisord" && echo "✅ Supervisor 开机自启成功" || echo "❌ 需检查面板自启配置"
# 3. 验证 Nginx 状态
sudo /xp/server/supervisor/supervisorctl status nginx | grep "RUNNING" && echo "✅ Nginx 被自动管理" || echo "❌ 需重新配置"

四、常用管理命令(后续维护)

功能 命令
查看 Nginx 状态 sudo /xp/server/supervisor/supervisorctl status nginx
手动重启 Nginx sudo /xp/server/supervisor/supervisorctl restart nginx
停止 Nginx sudo /xp/server/supervisor/supervisorctl stop nginx
启动 Nginx sudo /xp/server/supervisor/supervisorctl start nginx
查看 Supervisor 日志 tail -n 50 /xp/server/supervisor/log/supervisord.log
查看 Nginx 运行日志 tail -n 50 /xp/server/supervisor/log/nginx.out.log
重启 Supervisor pkill -9 supervisord && /xp/server/supervisor/supervisord -c /xp/server/supervisor/supervisord.conf

五、最终效果

  1. 主进程崩溃:15 秒内自动重启,新进程接管服务
  2. 全进程被杀:自动清场端口 + 重启,端口重新绑定
  3. 服务器重启:Supervisor 随面板自启,Nginx 自动启动
  4. 无需手动干预:全程无人值守,确保网站稳定运行
继续阅读
元宵寄思 刘志强

元宵寄思

  寒雪纷飞落异乡,元宵佳节独凭窗。 烟花璀璨添愁绪,灯火阑珊惹断肠。 妻女音容常入梦,椿萱身影每盈眶。 谋生苦累归期杳,唯盼团圆岁月长。
切莫酒后一时快语悔恨终生 重温2013年随笔…… 刘志强

切莫酒后一时快语悔恨终生 重温2013年随笔……

今天翻看邮箱无意发现一篇随笔,对比现在发现变化不大,也许岁月磨平了棱角,可内心依旧冲动烦躁,事业没进步是对的,几十年的性格不能说变就变,也许是“出淤泥而不染”。 咱已过不惑之年,何为不惑,意为不在疑惑...
论饭局中女人的重要性 刘志强

论饭局中女人的重要性

线上冲浪,无意间看到此文,为何转载?作为天天酒局之人,对其部分观点比较认可,最主要此文文笔风格,像极了我一天天喝酒的湖北哥们,如果不看出处,我还以为是他手笔。 原标题:如果没有女人,再荤的饭局也都是“...
为什么说“少年戒色 中年戒斗 晚年戒得“ 刘志强

为什么说“少年戒色 中年戒斗 晚年戒得“

孔子曰:“君子有三戒,少之时,血气未定,戒之在色;及其壮也,血气方刚,戒之在斗;及其老也,血气既衰,戒之在得。” 人活着,面对纷繁复杂的世界,要懂得节制自己。 人生道路崎岖,行走路上挫折不断,但这辈子...
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: