使用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 在 stop
和 restart
时,会发送 stopSignal
和 killSignal
给进程,信号量默认为 TERM
,就是 15
。
一般的 java 程序未处理这个信号量,或者是通过 start.sh
启动的 java 主进程。这样的情况,则无法通过 TERM
信号量杀死进程,或者会产生一个孤儿进程。
正确方法
- 直接使用 java 启动进程,不添加
start.sh
等 shell 来启动,因为 shell 无法处理信号量,无法回收子进程 stopsignal=TERM
改成stopsignal=QUIT
或者 `stopsignal=KILL
- 添加
stopasgroup=true
和killasgroup=true
扩展解读
之前专门写过信号量的文章(k8s 中有大量需要处理信号量的场景)