如何防止ctrl + c杀死Java中的衍生进程

时间:2014-07-29 09:58:51

标签: java

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

有关

我希望能够从一个“管理器”Java进程中生成外部进程(shell脚本),这个进程应该在JVM被杀死时继续运行 - 但是当我杀死父Java程序时,孩子也被杀死了(请注意,如果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:按照How to gracefully handle the SIGKILL signal in Java中的描述添加关闭钩子不会阻止传播给孩子的 Ctrl + c

3 个答案:

答案 0 :(得分:3)

弗拉基米尔给出了我们需要的暗示! (对不起,打败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进程分离了!

答案 1 :(得分:1)

在Linux中,如果你开始另一个过程,那就是你的孩子,你就是他的父母。如果父母被杀,所有的孩子都会被杀,他们的孩子也会被杀死(这是多么可怕的暴行)。

您需要的是开始一个在退出程序时不会被杀的进程。所以,你需要生育不是自己的孩子。例如,这里描述了执行此操作的方法:Linux: Prevent a background process from being stopped after closing SSH client例如使用screen实用程序。

答案 2 :(得分:0)

你必须把它变成一个守护进程。不要害怕它不是恐怖电影。您只需要将您的进程从控制终端会话中分离出来。我总是以相反的方式做到这一点:启动Java的shell脚本。

以下是解释:

http://en.wikipedia.org/wiki/Daemon_(computing)

你也可以" jvm关闭钩子",但它们在某些情况下不起作用。