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

[NB。 这与我如何从Java程序启动完全独立的进程有关? 但不同]

我希望能够从一个“管理器”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。

编辑1:将exec更改为

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

没有帮助。

编辑2:按照如何在Java中正常处理SIGKILL信号中所述添加关闭挂钩不会停止将Ctrl + c传播给子节点。


弗拉基米尔给了我们需要的提示! (对不起,击败卢卡斯)

添加另一个脚本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进程!


在Linux中,如果你启动另一个进程,它是你的孩子,你是他的父母。 如果父母遇害,所有的孩子都会被杀害,他们的孩子也会被杀害(这是一种可怕的暴行)。

你需要的是启动一个当你退出程序时不会被杀死的进程。 所以,你需要生下不是你自己的孩子。 例如,在这里描述的方法如下:Linux:关闭SSH客户端后禁止后台进程停止,例如使用screen实用程序。


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

这里是一个解释:

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

你也可以使用“jvm shutdown hooks”,但它们在某些情况下不起作用。

链接地址: http://www.djcxy.com/p/80645.html

上一篇: How to prevent ctrl+c killing spawned processes in Java

下一篇: based DLL in a non