Runtime.getRunTime().exec not behaving like C language "system()" command
Asked Answered
M

5

6

In "C", I can run a long blocking process in the background (AND HAVE IT CONTINUE TO RUN) after the starting process has exited.

void main(void)
{
      system("some_long_blocking_process &");
      exit();
}

// "some_long_blocking_process" is still running here (DESIRED BEHAVIOR)

Java's getRuntime().exec() DOESN'T have this behavior. Instead, "some_long_blocking_process" ends immediately when the Java process ends.

Anyone know how I can recapture this behavior in Java?

  1. I am using Java 1.4 (No process builder)
  2. I specifically am looking to start the long blocking process and to exit immediately (no "waitFor(), etc.)
  3. Things I have already tried (the process runs correctly, but I still get the same undesired behavior)
    • adding "nohup" and run in foreground ("nohup some_long_process")
    • adding "nohup" and running in background ("nohup some_long_process &")
    • run in foreground ("some_long_process")
    • run in background ("some_long_process &")

THANKS!

Thanks to all the suggestions... I've decided to use jtahlborn's answer (it worked for me)

Martial answered 5/10, 2011 at 17:24 Comment(0)
T
4

the only way we were able to achieve this with java was to add another layer of script. you need a simple wrapper script which invokes the app you actually want to run, e.g.:

runner.sh:

#!/bin/sh

nohup "$@" > /dev/null 2>&1 &

then invoke "/bin/sh runner.sh the real command" from your java program.

Tutuila answered 5/10, 2011 at 18:21 Comment(0)
D
5

try this:

String[] cmd = {"/bin/sh", "-c", "yourcommand args"};
Process p = Runtime.getRuntime().exec(cmd);

when redirect stream to /dev/null:

String[] cmd = {"/bin/sh", "-c", "yourcommand args > /dev/null 2>&1 &"};
Process p = Runtime.getRuntime().exec(cmd);
Duplex answered 17/12, 2012 at 6:57 Comment(1)
That also worked for me. As a advantage over the selected solution, there is no need to write a new runner script with this solution.Stonecrop
T
4

the only way we were able to achieve this with java was to add another layer of script. you need a simple wrapper script which invokes the app you actually want to run, e.g.:

runner.sh:

#!/bin/sh

nohup "$@" > /dev/null 2>&1 &

then invoke "/bin/sh runner.sh the real command" from your java program.

Tutuila answered 5/10, 2011 at 18:21 Comment(0)
T
1

EDIT:

Have your tried this?

Runtime.getRuntime().exec("/bin/sh -c /usr/X11/bin/xterm &")

This worked for me on MacOS.

Previous answer (JDK 1.5, apologies for not reading the question correctly):

To execute a process without waiting you can use the ProcessBuilder

ProcessBuilder pb = new ProcessBuilder("/usr/X11/bin/xterm");
pb.start();
Thyme answered 5/10, 2011 at 18:20 Comment(3)
He says "I am using Java 1.4 (No process builder)."Heeling
@DerekSpringer: Thanks I missed that.Thyme
Thanks, that looks like it will work. But I've already used jtahlborn's suggestion.Martial
E
0

Your problem is probably due to the trailing &. Try removing it.

getRuntime().exec() is more similar to fork() and exec() than system().

system() passes the command to the shell, and it's Bash that understands that the trailing ampersand means to run the process in the background.

getRuntime().exec() parses the command using a StringTokenizer to parse the command, and doesn't do anything with the trailing ampersand. That's simply passed as the first argument to your some_long_blocking_process, which may exit out immediately on the unknown error.

Equi answered 5/10, 2011 at 17:47 Comment(1)
Thanks, I'd already tried that. (Doesn't work) -- I've edited my original post to reflect what I've tried.Martial
H
0

Have you tried spawning a new Thread to run the executable? Try:

new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            Runtime.getRuntime().exec(<your exec>);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}).run();

This way, the main process won't shutdown until the exec has finished running (and the thread has finished).

Also, don't manually call exit() in your application unless you have some overwhelming reason to--the JVM does a good job of detecting when the application has finished on its own. This way, you won't force close threads that are running in the background.

Heeling answered 5/10, 2011 at 18:31 Comment(1)
This is a GUI application, so the exit() condition is required.Martial

© 2022 - 2024 — McMap. All rights reserved.