在Linux中,您可以提供以下命令:
service <someService> start
service <someService> stop
与使用kill -9 <someService>
杀死进程相反。正如我在之前的一个问题中所了解的那样,这是将进程发送到SIGTERM
(前者)和SIGKILL
(后者)之间的区别。
那么如何将普通JAR或WAR作为可以使用这些命令启动和停止的服务/守护进程“注册”(和编码)?我认为Java必须有一些API来处理SIGTERM
s?
提前致谢!
答案 0 :(得分:35)
如果你只想运行一些关闭特定的代码,处理它的“正确的Java”方式不会使用信号,而是添加一个通用的“关闭钩子”,当你的应用程序即将终止时它会运行。这是Java有时会遇到的最不常见的问题之一。 (由于并非所有平台都支持SIGINT
,因此在Java中,没有平台支持SIGINT
。)
不幸的是,您在ShutdownHook
中没有获得太多上下文,但它可能仍然有用:
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
public void run()
{
// cleanup
}
}));
如果你真的需要区分收到的信号,或者你想要支持Java通常忽略的信号(如USR1
),或者你想根据信号中止关机,那么{{1}不幸的是,对你来说将是无用的。
使用ShutdownHook
类,有一种不受支持的,记录不完整的方法来捕获Sun JVM中的信号。虽然它似乎是IBM JVM also supports this。
例如 - 您可以连接一个信号处理程序来监听sun.misc.SignalHandler
重新加载您的服务器配置,该配置在SIGHUP
脚本中设置为init.d
动词:
reload
至于使用Signal.handle(new Signal("HUP"), new SignalHandler() {
public void handle(Signal signal)
{
reloadConfiguration();
}
});
命令配置要控制的Java应用程序,您应该在system
程序中编写一个启动它的shell脚本。这只需要回复init.d
和start
动词并采取适当的行动。例如,这可能是您的stop
:
/etc/init.d/my-java-program
您现在可以通过运行#!/bin/sh
case "$1" in
start)
java /path/to/my/java/program.jar &
echo $! > /var/run/my-java-program.pid
;;
stop)
if [ ! -f /var/run/my-java-program.pid ]; then
echo "my-java-program: not running"
exit 1
fi
kill -TERM `cat /var/run/my-java-program.pid`
;;
reload)
if [ ! -f /var/run/my-java-program.pid ]; then
echo "my-java-program: not running"
exit 1
fi
kill -HUP `cat /var/run/my-java-program.pid`
;;
*)
echo "Usage: /etc/init.d/my-java-program {start|stop|reload}"
exit 1
;;
esac
exit 0
启动应用程序,或者在CentOS上启动应用程序,也可以使用service my-java-program start`。
答案 1 :(得分:3)
您无法像在本机Unix程序中那样为纯Java中的不同信号定义信号处理程序。这意味着您不能遵循例如惯例。让程序在SIGHUP
上重新加载其配置,并在SIGINT
或SIGTERM
上执行干净关闭。
您可以做的是定义shutdown hook。它们在虚拟机将要关闭时运行,例如,收到SIGTERM
后。这是一个例子:
Runnable myShutdownHook = new Runnable() {
void run() {
System.out.println("I'm melting! What a world...");
}
};
Runtime.getRuntime().addShutdownHook(new Thread(myShutdownHook));