[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 。
答案 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
答案 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关闭钩子",但它们在某些情况下不起作用。