Java 来自UNIX的关闭钩子

Java 来自UNIX的关闭钩子,java,unix,shutdown-hook,Java,Unix,Shutdown Hook,我试图让我的Java程序在unix服务器上正常退出。我有一个jar文件,我在早上通过cron作业启动它。然后在晚上,当我想关闭它时,我有一个cron作业,它调用一个脚本来查找PID并调用kill-9。然而,当我以这种方式终止时,我的关闭挂钩似乎并没有被激活。我也尝试过杀掉(no-9),我也遇到了同样的问题。如何确保调用关闭挂钩?或者,也许有更好的方法每天终止我的进程 class ShutdownHook { ShutdownHook() {} public void atta

我试图让我的Java程序在unix服务器上正常退出。我有一个jar文件,我在早上通过cron作业启动它。然后在晚上,当我想关闭它时,我有一个cron作业,它调用一个脚本来查找PID并调用
kill-9
。然而,当我以这种方式终止时,我的关闭挂钩似乎并没有被激活。我也尝试过杀掉(no-9),我也遇到了同样的问题。如何确保调用关闭挂钩?或者,也许有更好的方法每天终止我的进程

class ShutdownHook {

    ShutdownHook() {}

    public void attachShutDownHook() {

        Runtime.getRuntime().addShutdownHook(new Thread() {
        @Override
        public void run() {
                System.out.println("Shut down hook activating");
         }
        });
        System.out.println("Shut Down Hook Attached.");
    }   
}

您可以在Unix上使用如下代码捕获SIGINT(#2)信号:

kill-9
发送一个
kill
信号。该信号不能被程序截获


如果您调用
kill
,将发送
术语
信号(15)。在这种情况下,JVM将捕获信号,并执行关闭挂钩。

这与JVM捕获/接收的信号无关,而是与Gnome可怕的关闭过程有关,显然需要合作,以避免彻底破坏床(jdk没有用于此的api)。如果您想看到更糟糕的后果,请尝试运行:

dbus-monitor --profile --session type='method_call',interface='org.gnome.SessionManager'
在shell上,然后注销或重新启动:它将使gnome shell崩溃并挂起计算机,直到您登录TTY并命令重新启动。 也许kdbus会解决这个问题,也许不会。我知道的唯一一件事是,使用AWT(而不是命令行)的java应用程序上的shutdownhooks永远不会在GNOME3上运行它的shutdownhooks。实际上,虚拟机将始终以非零代码(失败)退出,这可能来自本机代码。至少它没有挂起,尽管这使得关闭挂钩非常无用
(我一直在尝试通过使用dbus监视器来解决问题,但正如您从我给出的示例中看到的,这也有点太危险了)。

kill-9
是保证的UNIX i-don-care-if-you-printing-rainbows-you-will-halt-NOW标志。使用它不会给你一个很好的关机。它也不能被困住。我想知道的是,您是否在代码中的任何地方使用了
System.exit()
,这可能是一个好的开始。本文()似乎表明SIGTERM生成了一个Java System.exit(),因此exit钩子应该可以工作。您是否通过在JVM中生成System.exit()来测试钩子行为?可能您使用了错误的PID.Hmm,确实很奇怪。你是对的。我添加了一个
System.exit(0)插入挂钩后调用。在windows上的Eclipse环境中,我看到应用了关闭钩子,但当我将其装入jar并将其移植到我的unix服务器时,我看到应用程序关闭,但没有关闭钩子…@Roman它肯定是正确的,但问题中的kill-9决不能被捕获。@IngoKegel:非常正确,unix设计师构建了SIGKILL(9)这样做只是为了没有程序可以忽略/处理该信号。所以你的答案不适用于这个问题。此外,出于清理目的捕获kill信号是通过shutdown hook完成的,您不需要使用
sun.misc.
包中的类来实现这一点。我尝试了
kill-9
kill
,只是没有看到应用shutdown hook。我还尝试将
系统.exit(1)
插入到我的代码中,但当我通过unix将其作为jar运行时,我看不到关机钩子一般会激活
kill
(没有-9)和
系统。exit(1)
肯定会执行关机钩子。由于某种原因,您的JRE似乎无法捕获这些信号。您可以尝试使用不同的JRE。我在我的ubuntu服务器上运行:java版本“1.6.0_23”OpenJDK运行时环境(IcedTea6 1.11pre)(6b23~pre11-0ubuntu1.11.10.2)OpenJDK客户端虚拟机(构建20.0-b11,混合模式,共享)
dbus-monitor --profile --session type='method_call',interface='org.gnome.SessionManager'