java - 如何防止 ctrl+c 杀死 Java 中生成的进程

标签 java

[注意。这与 How do I launch a completely independent process from a Java program? 有关但不同]

我希望能够从“管理器”Java 进程中生成外部进程(shell 脚本),当 JVM 被杀死时,该进程应该继续运行 - 但似乎当我杀死父 Java 程序时, child 也被杀死了(请注意,如果 JVM 自然退出,行为会有所不同)。我有的最简单的测试程序是:

public class Runit {

    public static void main(String args[]) throws IOException, InterruptedException {
        Runtime.getRuntime().exec(args[0]);

        // doesn't work this way either
        // ProcessBuilder pb = new ProcessBuilder(args[0]);
        // pb.start();

        while (true) {
            System.out.println("Kill me");
            Thread.sleep(2000);
        }
    }
}

和外部脚本:

#!/bin/sh

while [ 1 ] ; do 
    ls
    sleep 1
done

运行方式

java -classpath jar-with-dependencies.jar temp.exec.Runit runit.sh

如果管理器简单地退出(即取出 Java 程序中的“while”循环),那么生成的进程会继续运行,但是当我 Ctrl+c Java 程序外部程序也被杀死,这不是我想要的。

我在 Ubuntu 上使用 OpenJDK 1.6。

Edit1:将 exec 更改为

Runtime.getRuntime().exec("/usr/bin/nohup " +  args[0]);

没有帮助。

Edit2:添加关闭 Hook ,如 How to gracefully handle the SIGKILL signal in Java 中所述不会阻止 Ctrl+c 传播给 child 。

最佳答案

Vladimir 给出了我们需要的提示! (抱歉,抢先了 Lukasz)

添加另一个脚本spawn_protect.sh

#!/bin/sh

LOG=$1
shift 

nohup $* > $LOG 2>&1  &

并将经理更改为:

public class Runit {
    public static void main(String args[]) throws IOException, InterruptedException {
        Runtime.getRuntime().exec(args);
        while (true) {
            System.out.println("Kill me");
            Thread.sleep(5000);
        }
    }
}

然后运行为:

java -classpath jar-with-dependencies.jar temp.exec.Runit spawn_protect.sh /tmp/runit.log runit.sh

现在 runit.sh 真正脱离了 JVM 进程!

关于java - 如何防止 ctrl+c 杀死 Java 中生成的进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25012662/

相关文章:

java - 没有滚动条的 JScrollPane

java - 错误 "Could not find com.android.support:appcompat-v7:22.2.0"

java - 查找最接近键最小值的值

java - DAO 和服务层(JPA/Hibernate + Spring)

java - 严重 : A child container failed during start java. util.concurrent.ExecutionException

java - 通过 uDeploy 在 Windows 命令行中将 java 作为单独的进程运行

java - 如何将docker容器日志保存在机器上而不是容器中

java - 如何在 servlet 操作中同步请求

java - 如何修复此代码以在 Android 应用程序的 Activity 之间传递数据?

java - Maven 发布插件无法提交 - E155010 节点路径有两次路径 - Cygwin 和 DOS