如何在Java中防止Ctrl+C终止生成的进程

7

[注:这与如何从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被传播到子进程。


这是哪个操作系统?Unix/Linux? - Jaco Van Niekerk
请参考https://dev59.com/QnE85IYBdhLWcg3w8IM4。目前似乎没有完美的解决方案。 - webuster
1
也许 $(runit.sh) 可以帮忙? - Vladimir Chervanev
3个回答

3

弗拉基米尔提供了我们需要的提示!(抱歉,比卢卡斯先到了)

添加另一个脚本 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
在Linux中,如果您启动另一个进程,它就是您的子进程,您是其父进程。如果父进程被杀死,则所有子进程以及它们的子进程也将被杀死(多么可怕的暴行)。
你需要的是启动一个进程,在您退出程序时不会被杀死。因此,您需要生产不属于自己的子进程。例如,Linux: Prevent a background process from being stopped after closing SSH client描述了实现此目标的方法,如使用screen工具。

0

你需要把它变成一个守护进程。别害怕,这不是恐怖电影。你需要将进程与控制终端会话分离。我通常是用相反的方式来做:通过shell脚本来启动Java。

以下是详细说明:

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

你也可以使用“JVM关闭挂钩”,但在某些情况下它们可能无法正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接