I am trying to execute a command via Runtime.getRuntime().exec()
.
When i run the following command in my linux bash it works fine.
Command: bash -c "npm -v"
But when i try to run it with Java it fails with the following error:
-v": -c: line 0: unexpected EOF while looking for matching `"'
-v": -c: line 1: syntax error: unexpected end of file
Reproducible example:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
public class RunACommandTest
{
public static void main(String[] args)
{
try
{
Process exec = Runtime.getRuntime().exec("bash -c \"npm -v\"");
new BufferedReader(new InputStreamReader(exec.getInputStream(), StandardCharsets.UTF_8))
.lines()
.forEachOrdered(line -> System.out.println("IN " line));
new BufferedReader(new InputStreamReader(exec.getErrorStream(), StandardCharsets.UTF_8))
.lines()
.forEachOrdered(line -> System.out.println("ERR " line));
}
catch(IOException e)
{
throw new RuntimeException(e);
}
}
}
I have also tried to use single quotes instead of double quotes.
CodePudding user response:
Unfortunately the now deprecated Runtime.exec(String)
breaks up this command incorrectly as 4 argument command { "bash", "-c", "\"npm", "-v\"" }
. Separating the parameter list as 3 argument command { "bash", "-c", "npm -v" }
will avoid this problem.
It is easier to use ProcessBuilder
which is used internally by Runtime.exec
:
ProcessBuilder pb = new ProcessBuilder("bash","-c", "npm -v");
Process exec = pb.start();
Note that you must consume stdout stderr in separate threads. What you have above may work, but it may freeze for other processes or conditions. You can avoid by redirect to file, or redirect error to stdout with:
pb.redirectErrorStream(true);