【问题标题】:Shutdown hook from UNIX来自 UNIX 的关闭挂钩
【发布时间】:2012-10-25 18:38:40
【问题描述】:

我正在尝试让我的 Java 程序在我的 unix 服务器上正常退出。我有一个 jar 文件,我从早上的 cron 作业开始。然后在晚上,当我想关闭它时,我有一个 cron 作业,它调用一个找到 PID 并调用 kill -9 <PID> 的脚本。但是,当我以这种方式终止时,似乎没有激活我的关闭挂钩。我也试过kill <PID>(没有-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.");
    }   
}

【问题讨论】:

  • kill -9 是保证的 UNIX I-don't-care-if-you're-printing-rainbows-you-will-halt-NOW 标志。使用它不会给你一个很好的关机。它也不能被困住。我想知道的是,如果您在代码中的任何位置使用 System.exit() - 这可能是一个好的开始。
  • 这篇文章 (link) 似乎表明 SIGTERM 生成了一个 Java System.exit(),因此退出挂钩应该可以工作。您是否通过在 JVM 中生成 System.exit() 来测试钩子行为?
  • 可能你使用了错误的 PID。
  • 嗯,确实很奇怪。你说的对。插入钩子后,我添加了一个System.exit(0); 调用。在 Windows 上的 Eclipse 环境中,我看到正在应用关闭挂钩,但是当我将其启动并将其移植到我的 unix 服务器时,我看到应用程序正在关闭,但没有关闭挂钩......
  • @Roman 这绝对是正确的 PID

标签: java unix shutdown-hook


【解决方案1】:

您可以在 Unix 上使用这样的代码来捕获 SIGINT (#2) 信号:

Signal.handle(new Signal("INT"), new SignalHandler() {
      public void handle(Signal sig) {
      // Forced exit
      System.exit(1);
   }
});

【讨论】:

  • 但问题中的kill -9 永远不会被困住。
  • @IngoKegel:非常正确,Unix 设计者构建 SIGKILL (9) 只是为了没有程序可以忽略/处理该信号。
  • 所以你的回答不适用于这个问题。此外,为了清理目的捕获终止信号是通过关闭挂钩完成的,您实际上并不需要 sun.misc. 包中的类。
【解决方案2】:

kill -9 <pid> 发送一个KILL 信号。该信号无法被程序截获。

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

【讨论】:

  • 我尝试了kill -9kill,只是没有看到应用了关闭挂钩。我还尝试在我的代码中插入一个System.exit(1),但是当我通过 unix 将它作为 jar 运行时,我没有看到关闭挂钩激活
  • 一般kill(没有-9)和System.exit(1)肯定会执行关机钩子。您的 JRE 似乎由于某种原因无法捕获这些信号。您可以尝试使用不同的 JRE。
  • 我在我的 ubuntu 服务器上运行:java 版本 "1.6.0_23" OpenJDK Runtime Environment (IcedTea6 1.11pre) (6b23~pre11-0ubuntu1.11.10.2) OpenJDK Client VM (build 20.0- b11,混合模式,共享)
【解决方案3】:

这与 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。实际上,VM 将始终以可能来自本机代码的非零代码(失败)退出。至少它不会挂起,尽管这使得关闭挂钩非常无用 (我一直在尝试使用 dbus-monitor 来解决这个问题,但是从我给出的示例中可以看出,它也有点太危险了)。

【讨论】:

    猜你喜欢
    • 2011-07-20
    • 1970-01-01
    • 1970-01-01
    • 2015-09-22
    • 2011-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多