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

Java进程返回退出码1时如何终止supervisord主进程?

问题排查与解决方案

问题背景

我通过supervisord管理3个子进程,其中Java进程sgw的配置如下:

[program:sgw]
command=java -jar test.jar
process_name=%(program_name)s
autostart=true
autorestart=unexpected
exitcodes=1
killasgroup=true
stopasgroup=true
stopsignal=TERM
startsec=0

配置autorestart=unexpected和exitcodes=1是为了让Java进程返回退出码1时不再重启。同时我希望该Java进程退出时终止supervisord并停止另外两个子进程,于是配置了事件监听器:

[eventlistener:processes]
command=/bin/bash -c ". /etc/stop-supervisor.sh"
events=PROCESS_STATE_STOPPED, PROCESS_STATE_EXITED, PROCESS_STATE_FATAL, PROCESS_STATE_UNKNOWN, PROCESS_STATE_BACKOFF

对应的脚本/etc/stop-supervisord.sh内容:

#!/bin/bash

printf "READY\n";

while read line; do
  echo "Processing Event: $line" >&2;
  kill -3 $(cat "/data/logs/supervisord.pid")
done < /dev/stdin

目前Java进程已退出,但supervisord仍在运行,另外两个子进程也未停止。


问题根源

  1. 信号选择错误:kill -3发送的是QUIT信号,supervisord收到该信号后只会尝试优雅关闭,但默认不会主动终止所有子进程,且部分场景下可能无法正常退出。
  2. 脚本执行方式不当:使用. /etc/stop-supervisor.sh是source脚本而非直接执行,可能导致执行上下文异常,无法正确触发kill操作。
  3. 事件监听范围冗余且未做进程过滤:监听多种状态事件但未判断触发事件的进程是否为目标Java进程,同时可能因为事件触发逻辑不匹配导致脚本未执行。

修复步骤

1. 调整事件监听器配置

修改监听器的执行命令为直接调用脚本,并缩小事件监听范围到PROCESS_STATE_EXITED(Java进程退出码1会触发该事件):

[eventlistener:processes]
command=/etc/stop-supervisor.sh
events=PROCESS_STATE_EXITED
user=root  # 根据supervisord运行用户调整,确保拥有kill权限

2. 修正停止脚本逻辑

更新/etc/stop-supervisord.sh,添加进程过滤逻辑,并使用TERM信号终止supervisord(supervisord收到TERM信号会自动停止所有子进程):

#!/bin/bash

printf "READY\n";

while read -r event_line; do
  echo "Processing event: $event_line" >&2
  # 从事件行中解析出进程名
  target_process=$(echo "$event_line" | awk -F':' '{print $2}' | awk '{print $1}')
  # 仅处理目标Java进程sgw的退出事件
  if [ "$target_process" = "sgw" ]; then
    # 发送TERM信号终止supervisord,触发所有子进程停止
    kill -TERM $(cat "/data/logs/supervisord.pid")
    # 退出循环避免重复执行
    exit 0
  fi
done < /dev/stdin

给脚本添加可执行权限:

chmod +x /etc/stop-supervisord.sh

3. 优化supervisord全局配置(可选)

在supervisord主配置文件中添加超时停止配置,确保子进程在超时后被强制终止:

[supervisord]
stopwaitsecs=10  # 等待子进程优雅退出的超时时间,超时后发送KILL信号

4. 验证配置

重启supervisord加载新配置:

supervisorctl reload

测试Java进程退出后,检查supervisord是否终止,同时另外两个子进程是否已停止。可以通过查看supervisord日志确认事件触发情况:

tail -f /data/logs/supervisord.log  # 替换为实际日志路径

内容的提问来源于stack exchange,提问作者Ganesh Shinde

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 22:50:23