0

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.

1
  • 1
    I'm not that proficient with Java, but on your command line, bash sees two parameters: -c and ' npm -v. From your Java environment, you let bash see three parameters: -c, "-npm` and -v". This can't be right. It is the reason for the error looking for matching `"' Commented Jul 27, 2022 at 9:43

1 Answer 1

1

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);
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much! Yes, above was just an example. I use CompleableFutures to read the stdout and stderr. But i never knew there was an option like redirectErrorStream. This is saving me much time!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.