【问题标题】:Graceful kill of Apache Commons Exec process优雅地杀死 Apache Commons Exec 进程
【发布时间】:2011-03-02 22:39:25
【问题描述】:

我正在我的 Java 程序(在 Linux 上)中启动一个外部进程,我需要能够向它发送 SIGTERM 信号,而不是 exec.getWatchdog().destroyProcess() 正在发送的 SIGKILL。有没有一种方法可以更优雅地停止以 commons-exec 启动的 unix 进程?或者我可以获取 PID,以便我自己运行适当的 kill 命令?

【问题讨论】:

    标签: java unix apache-commons apache-commons-exec


    【解决方案1】:

    ExecuteWatchdog 类有杀死进程的方法。

    因此,您可以创建一个具有较长超时时间的看门狗,并在必要时使用它来终止进程,即

    executor.getWatchdog().destroyProcess();
    

    【讨论】:

    • 正确,但是会发送 SIGKILL。问题是如何发送不同的信号,例如 SIGTERM 以更优雅地停止它。
    • @audras 其实你最好使用new ExecuteWatchdog(ExecuteWatchdog.INFINITE_TIMEOUT),而不是long timeout。
    【解决方案2】:

    嗯,Commons Exec 依赖于 Java Process 类,它不公开 PID。它也是用来杀死进程的东西,所以你不能改变它的行为。一切都很好,封装。一定要爱OO,嗯?

    如果您只是在后台启动进程,您可以将它们包装在一个简单的 shell 脚本中,该脚本为您捕获 PID,然后将其保存到您的 Java 例程知道的“已知位置”。还是有点乱,而且自然不能很好地移植到其他平台。

    您也可以使用 JNI 编写自己的 exec 函数来为您捕获此信息,但这可能不太友好。

    您可以使用更面向系统(C、Python 等)的方式编写特定于平台的 exec 启动器守护程序。您发送 IT 消息来启动和停止事物,它会为您处理该过程。这样做的一个好处是,您不必在运行新进程时分叉 JVM(这可能会非常昂贵,具体取决于您的 JVM 大小)。

    您可以从一开始就启动守护程序并共享一个套接字或管道(两者都非常便携)。这实际上不是一个可怕的 Inelegant 解决方案,它划分了许多系统特定的行为(所以你可以在 Windows 和 Unix 上拥有完全不同的进程,而你的 Java 保持不变,你只需要移植你的小守护进程),无需运行 JNI。

    【讨论】:

    • 是的,这是一个从 shell 脚本执行 java jar 的好主意,这样你就知道要杀死哪个了。 +1
    • 好的,谢谢你的信息。他们没有公开这种功能真的很奇怪,我只需要在 python 中解决它。无赖。
    【解决方案3】:

    你可以用 grep 表示,例如:

    for i in $(ps -ef | grep -i "[Y]ourClassName" | awk '{print $2}'); do kill -9 $i; done
    

    这是在你让它运行超过 1 次的情况下(虽然它在你只有一个项目的情况下可以工作),请注意 grep 中的 [],这样 grep 不会给你自己的进程 pid 和-i 代表忽略大小写,awk 仅用于打印第二列即 PID 号。

    【讨论】:

    • 这是一种可能性,但我有多个调用相同的脚本正在运行,我真的只想停止外部进程启动的那个,而不是尝试使用命令行。我认为没有办法从 commons-exec 获取 PID?
    • @jtb 如果你问我,Will Hartung 有一个更好的主意,只需用 shell 脚本包装你的 jar,你仍然可以使用这个 grep 或另一个来杀死你想要的那个。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-28
    • 2014-10-18
    • 1970-01-01
    • 2016-11-12
    • 1970-01-01
    • 2019-07-19
    相关资源
    最近更新 更多