supervisor杀死不掉程序的问题分析
项目场景:
supervisor可以说是linux上大名鼎鼎的守护进程工具了,它的易用性在我所有用过的工具里算是排名前列的。但在使用过程中也不免会出一些问题,很多都是设置错误导致的。
问题描述
使用java启动一个jar,调用stop的时候jar程序还是留存在后台。
原因分析:
这并不是supervisor的bug,也不是你的程序写的有问题。由于很多java项目都需要初始化很多变量,很多人选择了在shell里面导出环境变量,然后在shell里面启动java程序。
这样导致一个问题,supervisor守护进程守护的不是你的jar,而是你用来初始化环境变量的shell脚本。所以导致了stop之后java程序留存后台的问题。
解决方案:
这可能也是supervisor的运作机制导致的,如果你不用初始化变量,你就直接在command里面启动jar就行了,如果你你必须初始化变量不如使用supervisor自带的environment字段配置变量。
下面是错误
的写法:
xf.conf
[program:xf]
directory=/home/anold/XTTS
command=bash xf_tts.sh
autostart=true
autorestart=true
user=root
redirect_stderr=true
stdout_logfile = /home/anold/XTTS/starts.log
stdout_logfile_maxbytes = 50MB
staout_logfile_backups = 5
xf_tts.sh
#!/bin/bash
export LD_LIBRARY_PATH=/home/anold/XTTS/libs:$LD_LIBRARY_PATH
echo "LD_LIBRARY_PATH: $LD_LIBRARY_PATH"
echo "Directory: " && pwd
java -jar xf_tts_demo-1.0-SNAPSHOT.jar
上面的写法会在supervisorctl
调用stop
之后杀死xf_tts.sh
而不是xf_tts_demo-1.0-SNAPSHOT.jar
,因为xf_tts.sh
是xf_tts_demo-1.0-SNAPSHOT.jar
的父进程,当父进程被杀死,子进程就成了孤儿进程最终被systemd托管,所以可以一直存活,直到自己崩溃为止!
下面是正确
的写法:
[program:xf]
directory=/home/anold/XTTS
command=java -jar xf_tts_demo-1.0-SNAPSHOT.jar
autostart=true
autorestart=true
user=root
redirect_stderr=true
stdout_logfile = /home/anold/XTTS/starts.log
stdout_logfile_maxbytes = 50MB
staout_logfile_backups = 5
environment=LD_LIBRARY_PATH="/home/anold/XTTS/libs",NAME="anold"
environment里面配置的环境变量会代入subprogress,这样你可以在command里面读取到。这样就同时解决了环境变量和程序杀不死的问题。
总结:
supervisor这个工具用好很重要,我觉得是linux必不可少的神器。但是,神器有时候有它自己的脾气。