-->

Apache Commons Exec produces too many quotes for a

2019-02-16 14:35发布

问题:

Either there is a bug in Apache Commons Exec, or I am using the API wrong, but when I use the CommandLine class to add a argument that contains spaces, some quotes are added and are then part of the argument that is given.

For example: When I call java "what version" I get java.lang.NoClassDefFoundError: what version, and when I call java "\"what version\"" (which contains escaped quotes, that are part of the command line argument itself), I get java.lang.NoClassDefFoundError: "what version".

So the following test fails, because as you can see in the last line, Apache Exec is producing the latter version where it should have produced the first version:

@Test
public void testArgumentQuoting() throws Exception {
    DefaultExecutor executor = new DefaultExecutor();
    DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    PumpStreamHandler streamHandler = new PumpStreamHandler(out, out);
    executor.setStreamHandler(streamHandler);
    CommandLine cmdLine = new CommandLine("java");
    cmdLine.addArgument("what version");
    executor.execute(cmdLine, resultHandler);
    resultHandler.waitFor();
    String resultPattern = "Exception in thread \"main\" java\\.lang\\.NoClassDefFoundError: ([\\w \"]+)";
    Pattern pattern = Pattern.compile(resultPattern);
    Matcher matcher = pattern.matcher(out.toString());
    Assert.assertTrue(matcher.find());
    // Note: Result should be <what version> and NOT <"what version">!
    Assert.assertEquals("what version", matcher.group(1));
}

Now I want to know:

  • Is this a bug?
  • If so: Is there a way to circumvent this problem (a workaround)?
  • If not: What am I doing wrong?

Edit: I am trying to execute a process which I think fewest people will have on their machine. So I am using java instead as this command should be available on all machines where people develop Java. My point is that the wrong runtime argument is passed to the external process, containing escaped quotes, which it shouldn't.

Edit: I made this a filed bug for commons exec at Jira.

回答1:

This seems to be a real bug in Apache Commons Exec, which to date has not been fixed.



回答2:

Apache common exec has addArgument method with handleQuoting flag. If it's turned on, then it wraps arguments in quotation marks.

By default it's turned on

public CommandLine addArgument(final String argument, boolean handleQuoting) 


回答3:

you can try the next example it works for me :

  CommandLine cmdLine = new CommandLine("mco");
  cmdLine.addArgument("shellcmd" );
  cmdLine.addArguments( puppetAgents.split(" ") );
  cmdLine.addArgument("-t");
  cmdLine.addArgument(timeout);
  // When writing a command with space use double "
  cmdLine.addArgument("\"\"puppet agent -t\"\"",false);


回答4:

What class are you trying to execute? You're not specifying exactly what you want Java to execute. That needs to be your second argument.

In other words, if you're trying to run com.mycompany.MyExecutable, your code should look like this:

CommandLine cmdLine = new CommandLine("java com.mycompany.MyExecutable");

You can either append arguments after the CommandLine object is created.



回答5:

How about trying it this way as in the tutorial, to see if that makes a difference?

...
String line = "java what version";
CommandLine cmdLine = CommandLine.parse(line);
executor.execute(cmdLine, resultHandler);
...