You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何记录Supervisor中所有FATAL状态的进程?

问题描述

在PHP-Worker的Docker容器中,有若干关键进程需通过Supervisor管理,核心需求如下:

  1. 准确记录处于FATAL状态的进程
  2. 若关键进程进入FATAL状态则重启Docker容器
  3. 不需要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

配置步骤:

  1. 给脚本加执行权限:chmod +x check_supervisor_fatal.sh
  2. 添加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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 09:07:48