我在 Ubuntu 上终止 Java 程序时遇到问题。我创建了以下初始化脚本:
#!/bin/sh
### BEGIN INIT INFO
# Provides: control ...
# Required-Start: $remote_fs $network $syslog
# Required-Stop: $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: ...
# Description: ...
### END INIT INFO
DAEMON_PATH="/mnt/Data/wstlm"
DAEMON=startWstlm
DAEMONOPTS=""
NAME=wstlm
DESC="My daemon description"
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
case "$1" in
start)
printf "%-50s" "Starting $NAME..."
cd $DAEMON_PATH
PID=`./$DAEMON $DAEMONOPTS > /dev/null 2>&1 & echo $!`
echo "Saving PID" $PID " to " $PIDFILE
if [ -z $PID ]; then
printf "%s\n" "Fail"
else
echo $PID > $PIDFILE
printf "%s\n" "Ok"
fi
;;
status)
printf "%-50s" "Checking $NAME..."
if [ -f $PIDFILE ]; then
PID=`cat $PIDFILE`
if [ -z "`ps axf | grep ${PID} | grep -v grep`" ]; then
printf "%s\n" "Process dead but pidfile exists"
else
echo "Running"
fi
else
printf "%s\n" "Service not running"
fi
;;
stop)
printf "%-50s" "Stopping $NAME"
PID=`cat $PIDFILE`
cd $DAEMON_PATH
if [ -f $PIDFILE ]; then
kill -9 $PID
printf "%s\n" "Ok"
rm -f $PIDFILE
else
printf "%s\n" "pidfile not found"
fi
;;
restart)
$0 stop
$0 start
;;
*)
echo "Usage: $0 {status|start|stop|restart}"
exit 1
esac
这个初始化脚本将目录改变为我的程序,执行的startWstlm的内容是:
#!/bin/sh
echodate +"%Y/%m/%d %T"
- 启动 WSTLm 1>>/mnt/Data/wstlm/wstlm.log
java -Djavax.net.ssl.trustStore=jssecacerts -jar /mnt/Data/wstlm/myProgram.jar
我将 init 脚本添加到了 init.d。如果我调用
sudo 服务 myProgram 启动
程序正常启动。但如果我使用
sudo 服务 myProgram 停止
程序没有关闭。只有启动我的 java 程序的 bash 命令被终止。
执行停止之前:
1 根 /bin/sh ./startWstlm
2 根 java -Djavax.net.ssl.trustStore=jssecacerts -jar /mnt/Data/wstlm/myProgram.jar
3 根 java -Djavax.net.ssl.trustStore=jssecacerts -jar /mnt/Data/wstlm/myProgram.jar
4 根 java -Djavax.net.ssl.trustStore=jssecacerts -jar /mnt/Data/wstlm/myProgram.jar
执行停止后:
(注意这个 bash 被杀死了)
2 root java -Djavax.net.ssl.trustStore=jssecacerts -jar /mnt/Data/wstlm/myProgram.jar
3 root java -Djavax.net.ssl.trustStore=jssecacerts -jar /mnt/Data/wstlm/myProgram.jar
4 root java -Djavax.net.ssl.trustStore=jssecacerts -jar /mnt/Data/wstlm/myProgram.jar
(顺便问一下:这个jar为什么有多个进程?)
所以问题是我无法停止我的程序。这有点烦人。有人知道吗?
答案1
首先,不要使用kill -9
;简单的kill
就足够了。其次,参见这一页详细解释了当父进程被要求退出时如何终止子进程。在这种情况下,startWstim
需要在 Java 程序退出之前终止它。
最后,也许更简单的是省去startWstim
,而是直接在初始化脚本中执行它包含的命令:
start)
printf "%-50s" "Starting $NAME..."
cd $DAEMON_PATH
echo "$(date +"%Y/%m/%d %T") - start WSTLm" >> /mnt/Data/wstlm/wstlm.log
java -Djavax.net.ssl.trustStore=jssecacerts -jar /mnt/Data/wstlm/myProgram.jar &
PID=$!
请注意,您不需要子 shell 来获取 Java 程序的进程 ID,并且您需要捕获命令的输出date
以便将其打印到日志文件。