Java exec() does not return expected result of pipes' connected commands
Still didn't found proper solution to execute piped commands with Runtime.exec, but found a workaround. I've simply wrote these scripts to separate bash files. Then Runtime.exec calls these bash scripts and gets expected result.
Problem with run DOS command in Java
The angle brackets are redirection operators: <inputfile.txt causes the input to be read in from inputfile.txt instead of the keyboard, >outputfile.txt causes the output to be written to outputfile.txt instead of the screen. This facility is provided by the shell, however when invoking your program with the Java runtime the shell is not present. Invoke via the shell, like this:
Runtime.getRuntime().exec("cmd /c crf_test.exe model <inputfile.txt> outputfile.txt");
...or redirect input and output using facilities provided by Java; see e.g. this question.
How to make pipes work with Runtime.exec()?
Write a script, and execute the script instead of separate commands.
Pipe is a part of the shell, so you can also do something like this:
String[] cmd = {
"/bin/sh",
"-c",
"ls /etc | grep release"
};
Process p = Runtime.getRuntime().exec(cmd);
Capturing stdout when calling Runtime.exec
You need to capture both the std out and std err in the process. You can then write std out to a file/mail or similar.
See this article for more info, and in particular note the StreamGobbler
mechanism that captures stdout/err in separate threads. This is essential to prevent blocking and is the source of numerous errors if you don't do it properly!
Run linux command through java.
Here's what you need to do:
String command = "nm -l file1.o > file1.txt";
Process p = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", command});
The following "simple answer" WON'T WORK :
String command = "/bin/sh -c 'nm -l file1.o > file1.txt'";
Process p = Runtime.getRuntime().exec(command);
because the exec(String)
method splits its the string naively using whitespace as the separator and ignoring any quoting. So the above example is equivalent to supplying the following command / argument list.
new String[]{"/bin/sh", "-c", "'nm", "-l", "file1.o", ">", "file1.txt'"};
Java process.waitFor() does not return
xcopy
probably just happens to produce more output than move
, filling up the out-buffer and blocking until it is flushed. The default behavior in Java is to pipe the subprocess's stdout/stderr into InputStream
s that you are then required to read programmatically lest the subprocess's buffers overflow.
If the latter is the case, the solution is simple, and in fact you should do that anyway: use ProcessBuilder
to prepare the system call and call inheritIO
on it. This will reuse your parent process`s stdin and stdout for the subprocess.
A side note, xcopy
is a regular .exe
file and doesn't need wrapping into cmd.exe /c
.
Java getRuntime Exec
Your Java process and your script are deadlocked waiting on each other: you are waiting for the process to exit, the process is waiting for you to read the output.
It happens to work for ls -alF
and other commands with small outputs because they all fit in the pipe's buffer (64kib on my system).
Just move the p.waitFor()
below the while loop, and you'll have more luck:
private String executeCommand(String command) {
StringBuilder output = new StringBuilder();
BufferedReader reader = null;
Process p;
try {
p = Runtime.getRuntime().exec(command);
reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "\n");
}
p.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
If you additionally want this to work correctly with values containing spaces and certain other characters, you have to:
- Quote
"${args[0]}"
in your script. - Rewrite your
executeCommand
to useRuntime.exec(String[])
instead ofRuntime.exec(String)
.
Related Topics
How to Use Intent.Flag_Activity_Clear_Top to Clear the Activity Stack
Java Is Installed, in Listing, But Execution Produces "./Java: No Such File or Directory"
How to Use Chef to Update-Alternatives for Java Using Execute
How to Find a User's Home Directory on Linux or Unix
How to Use Linux Shared Libraries in Java
Hadoop Hdfs Showing Ls: '/Home/Hduser/Input/': No Such File or Directory Error
Why How to Successfully Move a File in Linux While It Is Being Written To
Hiding Strings in Obfuscated Code
Is It Legal to Call the Start Method Twice on the Same Thread
Firebase No Properties to Serialize Found on Class
Couldn't Install Netbeans 11.3 with Java 14 Due to Error: "Unsupported Jvm Version"
Execute a Linux Terminal Command in Java
Cannot Run Program "Mvn" Error=2, No Such File or Directory