如何使用 SIGKILL Process.destroy() 杀死 Java 中的 Linux 进程 SIGTERM

Posted

技术标签:

【中文标题】如何使用 SIGKILL Process.destroy() 杀死 Java 中的 Linux 进程 SIGTERM【英文标题】:how can I kill a Linux process in java with SIGKILL Process.destroy() does SIGTERM 【发布时间】:2011-02-26 09:05:32 【问题描述】:

在 Linux 中,当我在 java.lang.Process 对象上运行 destroy 函数(这是真正的类型 java.lang.UNIXProcess )时,它会发送一个 SIGTERM 信号来处理,有没有办法用 SIGKILL 杀死它?

【问题讨论】:

【参考方案1】:

Java 1.8 起

你可以调用destroyForcibly()方法,它默认调用destroy()方法,但是根据Java文档,ProcessBuilderRuntime.exec()返回的所有子进程都实现了这个方法。

【讨论】:

不幸的是,目前实现只是调用destroy()。见这里:bugs.openjdk.java.net/browse/JDK-8056139【参考方案2】:

如果您知道进程名称,您可以使用pkill

Runtime.getRuntime().exec("pkill firefox").waitFor();

【讨论】:

【参考方案3】:

斯蒂芬他的回答是正确的。我写了他说的:

public static int getUnixPID(Process process) throws Exception

    System.out.println(process.getClass().getName());
    if (process.getClass().getName().equals("java.lang.UNIXProcess"))
    
        Class cl = process.getClass();
        Field field = cl.getDeclaredField("pid");
        field.setAccessible(true);
        Object pidObject = field.get(process);
        return (Integer) pidObject;
     else
    
        throw new IllegalArgumentException("Needs to be a UNIXProcess");
    


public static int killUnixProcess(Process process) throws Exception

    int pid = getUnixPID(process);
    return Runtime.getRuntime().exec("kill " + pid).waitFor();

您也可以通过这种方式获取 pid:

public static int getPID() 
  String tmp = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
  tmp = tmp.split("@")[0];
  return Integer.valueOf(tmp);

【讨论】:

在 linux 上,我通过 java(交互式进程)运行命令:nslookup -> google,这会挂起进程,我无法杀死这个进程。所以现在我使用了你的建议,但它并没有终止这个过程,它只是挂起,我无法终止我的程序。我什至试图手动杀死pid,但无济于事,我该怎么办??? @Space Rocker:一个简单的杀戮会发送一个 SIGTERM。 “kill -9”发送一个 SIGKILL。尝试“kill -9 -1”:将 SIGKILL 发送到 pid > 1 的进程组中的所有进程。如果这没有杀死它,那么什么都不会。但这会奏效。 肯定用第二种方式获取自己的PID。 VisualVM 也是如此。前一种方式是丑陋的 hack,它不是跨平台的,并且可能无法在未来的 Java 版本中使用。 @Espinosa - 第二种方式也不便携。 getName 的 javadoc 说:“返回的名称字符串可以是任意字符串,Java 虚拟机实现可以选择在返回的名称字符串中嵌入特定于平台的有用信息。” 注意:可以选择,表示它也可以选择不。并且没有规范应该如何格式化这些信息。 从 Java 9 开始,您只需调用 process.pid() 即可获取进程 ID。【参考方案4】:

不使用纯 Java。

您最简单的替代方法是使用Runtime.exec()kill -9 <pid> 命令作为外部进程运行。

不幸的是,获取 PID 并不是那么简单。您要么需要使用反射黑魔法来访问private int pid 字段,要么会弄乱ps 命令的输出。

更新 - 实际上,还有另一种方法。创建一个小实用程序(C 程序、shell 脚本等)来运行真正的外部应用程序。对实用程序进行编码,使其记住子进程的 PID,并为 SIGTERM 设置一个信号处理程序,该处理程序将 SIGKILL 子进程。

【讨论】:

我可以这样或在JNI中这样做,虽然我不急于这样做,你怎么知道你要杀死的进程的pid? 首先感谢您的回复。反射和 JNI/exec 是我最后的手段,我想知道是否有人可以找到更优雅的方式来做到这一点。 我对包装刽子手也很严厉,实际上我的老板也很严厉:),所以我知道你知道没有直接的方法可以做到这一点。 如果您要进行系统库调用,请不要直接在 JNI 中进行...省去一些麻烦,而是在 JNA 中进行。 @AlexanderMalakhov - 不,它不可移植,因为 toString() 方法的 javadoc 没有指定字符串的格式。根据源代码,对于 Unix 上的 Oracle Java,ProcessUnixProcess 上的 toString() 方法不会被 Object.toString() 覆盖。您所看到的(充其量)是特定于 android 的。

以上是关于如何使用 SIGKILL Process.destroy() 杀死 Java 中的 Linux 进程 SIGTERM的主要内容,如果未能解决你的问题,请参考以下文章

程序接收信号:在 Instruments 中开始录制时“SIGKILL”

在 glDrawArrays() 上调试 SIGKILL。苹果手机

在 pycharm 上使用 keras-tensorflow 的 3D CNN(进程以退出代码 137 完成(被信号 9:SIGKILL 中断))

数据帧合并给出“进程以退出代码 137 完成(被信号 9 中断:SIGKILL)”

通过signall.SIGKILL在指定位置结束正在执行的进程

来自 GDB 的消息“在启动程序期间以信号 SIGKILL 终止”