How to prevent ctrl + c killing spawned processes in Java

[NB. This is due to How to start a completely independent process from a Java program? but different]

I want to be able to run external processes (shell scripts) from the manager Java process, which should work when the JVM is killed, but it seems that when I kill the parent Java program, the child is also killed (note that the behavior is different if the JVM comes out of it naturally). The simplest test program I have:

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); } } } 

and external script:

 #!/bin/sh while [ 1 ] ; do ls sleep 1 done 

runs as

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

If the manager just exits (that is, it takes out the β€œwhile” loop in the Java program), then the generated process continues to work, but when I press Ctrl + c , the Java program also kills the external program, which is not what I want.

I am using OpenJDK 1.6 on Ubuntu.

Edit1: change exec to

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

Does not help.

Edit2: adding a disconnect hook, as described in How to gracefully process a SIGKILL signal in Java , does not stop the spread of Ctrl + c to the child.

+7
java
source share
3 answers

Vladimir gave us a hint! (Sorry, beat Lukash)

Add another spawn_protect.sh script

 #!/bin/sh LOG=$1 shift nohup $* > $LOG 2>&1 & 

And change the manager to:

 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); } } } 

Then do as:

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

Now runit.sh is really disconnected from the JVM process!

+3
source share

On Linux, if you start another process, this is your child, and you are his parent. If a parent is killed, all the children are killed, and their children too (what a terrible atrocity).

What you need is to start a process that will not be killed when you exit your program. So you must not give birth to your own child. The methods described here are described here: Linux: prevent the background process from stopping after closing the SSH client , for example, use the screen utility.

+1
source share

You must make it a demon. Do not be afraid, this is not a horror movie. You just need to separate your processes from terminal session management. I always do this unknowingly: a shell script that runs Java.

Here is an explanation:

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

You can also use "jvm shutdown hooks", but they will not work in some situations.

0
source share

All Articles