如何记录Supervisor中所有FATAL状态的进程?
问题描述
在PHP-Worker的Docker容器中,有若干关键进程需通过Supervisor管理,核心需求如下:
- 准确记录处于FATAL状态的进程
- 若关键进程进入FATAL状态则重启Docker容器
- 不需要Supervisor自动重启进程(已掌握自动重启配置)
当前采用两个Cron Job实现:
- 第一个定时执行命令提取FATAL进程名并写入文件:
supervisorctl status | awk '{if ($2 =="FATAL") {split($1,a,":"); print a[1]}}' # 输出非空时将进程名写入文件
- 第二个定时检查文件是否存在,以及关键进程是否在文件中
但认为该方案冗余性较高,希望得到更优实现方式。
优化方案
方法1:合并Cron任务,单脚本完成全流程
无需拆分两个Cron任务,编写单个Shell脚本一次性完成FATAL进程检测、关键进程匹配与Docker重启逻辑,减少冗余步骤。
示例脚本check_supervisor_fatal.sh:
#!/bin/bash # 定义需监控的关键进程列表(按需修改) CRITICAL_PROCESSES=("php-worker" "queue-worker" "task-manager") # 获取所有FATAL状态的进程名 FATAL_PROCESSES=$(supervisorctl status | awk '{if ($2 == "FATAL") {split($1,a,":"); print a[1]}}') # 遍历关键进程,检查是否存在FATAL实例 for proc in "${CRITICAL_PROCESSES[@]}"; do if echo "$FATAL_PROCESSES" | grep -q "^$proc$"; then # 记录日志 echo "$(date): 关键进程$proc处于FATAL状态,重启Docker容器" >> /var/log/supervisor_fatal.log # 重启当前容器(通过hostname获取容器名,也可直接指定容器名) docker restart $(hostname) # 找到目标进程后立即触发重启,可根据需求改为全部检查后再操作 exit 0 fi done
配置步骤:
- 给脚本加执行权限:
chmod +x check_supervisor_fatal.sh - 添加Cron定时任务(示例为每分钟执行一次):
* * * * * /path/to/check_supervisor_fatal.sh
方法2:利用Supervisor事件通知机制(实时触发)
Supervisor支持通过eventlistener监听进程状态变化,当进程进入FATAL状态时直接触发自定义逻辑,比定时轮询更高效。
步骤1:编写事件监听脚本
示例Python脚本supervisor_fatal_listener.py:
#!/usr/bin/env python3 import sys import os def main(): # 关键进程列表 critical_procs = {"php-worker", "queue-worker", "task-manager"} while True: # 读取Supervisor事件头 line = sys.stdin.readline() if not line: break headers = dict(h.split(":") for h in line.strip().split()) payload_len = int(headers.get('len', 0)) payload = sys.stdin.read(payload_len).strip() # 监听PROCESS_STATE_FATAL事件 if headers.get('eventname') == 'PROCESS_STATE_FATAL': proc_name = payload.split('processname:')[1].split()[0] if proc_name in critical_procs: # 记录日志 with open('/var/log/supervisor_fatal.log', 'a') as f: f.write(f"{os.popen('date').read().strip()}: 关键进程{proc_name}进入FATAL状态,重启容器\n") # 重启Docker容器 os.system('docker restart $(hostname)') if __name__ == '__main__': main()
步骤2:配置Supervisor事件监听器
给脚本加执行权限:chmod +x supervisor_fatal_listener.py
在Supervisor配置文件中添加如下内容:
[eventlistener:fatal_monitor] command=/path/to/supervisor_fatal_listener.py events=PROCESS_STATE_FATAL stdout_logfile=/var/log/supervisor_fatal_listener.log stdout_logfile_maxbytes=10MB stdout_logfile_backups=3
步骤3:生效配置
重启Supervisor:supervisorctl reload
这种方式为实时触发,无需定时轮询,更贴合Supervisor的原生设计。
方法3:调用Supervisor XML-RPC接口查询
Supervisor提供XML-RPC接口,可直接编程获取进程状态,适合需要更灵活逻辑的场景。
示例Python脚本:
#!/usr/bin/env python3 import xmlrpc.client import os # 连接Supervisor XML-RPC服务(默认端口9001) server = xmlrpc.client.ServerProxy('http://localhost:9001/RPC2') # 关键进程列表 critical_procs = ["php-worker", "queue-worker", "task-manager"] # 获取所有进程状态 processes = server.supervisor.getAllProcessInfo() for proc in processes: if proc['statename'] == 'FATAL' and proc['name'] in critical_procs: # 记录日志并重启容器 log_content = f"{os.popen('date').read().strip()}: 关键进程{proc['name']}处于FATAL状态,重启容器\n" print(log_content.strip()) with open('/var/log/supervisor_fatal.log', 'a') as f: f.write(log_content) os.system('docker restart $(hostname)') exit(0)
可将该脚本配置为Cron定时执行,或改造为守护进程实现实时查询。
内容的提问来源于stack exchange,提问作者Qiulang
相关产品推荐
相关产品推荐

