使用supervisor管理 java 进程时,无法终止程序的解决办法

正确姿势

[program:api]
command=java -Dserver.port=18888 -jar taike-api-0.0.1-SNAPSHOT.jar
process_name=api
numprocs=1
directory=/wwwroot/api/
priority=999
autostart=true
autorestart=true
startsecs=10
startretries=3
exitcodes=0,2
stopsignal=QUIT
stopwaitsecs=10
redirect_stderr=true
stdout_logfile=/wwwroot/api/api.log
environment=HOME="/root",PATH=/usr/local/java/bin:%(ENV_PATH)s
killasgroup=true
stopasgroup=true
stopsignal=QUIT

原因解读

官方文档
http://supervisord.org/configuration.html?highlight=stopsignal

supervisor 在 stoprestart 时,会发送 stopSignalkillSignal 给进程,信号量默认为 TERM ,就是 15

一般的 java 程序未处理这个信号量,或者是通过 start.sh启动的 java 主进程。这样的情况,则无法通过 TERM 信号量杀死进程,或者会产生一个孤儿进程。

正确方法

  1. 直接使用 java 启动进程,不添加 start.sh 等 shell 来启动,因为 shell 无法处理信号量,无法回收子进程
  2. stopsignal=TERM 改成 stopsignal=QUIT 或者 `stopsignal=KILL
  3. 添加 stopasgroup=truekillasgroup=true

扩展解读

之前专门写过信号量的文章(k8s 中有大量需要处理信号量的场景)

https://www.4wei.cn/archives/1002822