可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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?
- I am using Java 1.4 (No process builder)
- I specifically am looking to start the long blocking process and to exit immediately (no "waitFor(), etc.)
- 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)
回答1:
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.
回答2:
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);
回答3:
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();
回答4:
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.
回答5:
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.