【问题标题】:Apache Commons Exec produces too many quotes for arguments containing spaces?Apache Commons Exec 为包含空格的参数生成过多引号?
【发布时间】:2011-02-07 22:09:47
【问题描述】:

Apache Commons Exec 中存在错误,或者我使用 API 错误,但是当我使用 CommandLine 类添加包含空格的参数时,会添加一些引号,然后作为参数的一部分已给出。

例如:当我调用java "what version" 时,我得到java.lang.NoClassDefFoundError: what version,当我调用java "\"what version\""(包含转义引号,这是命令行参数本身的一部分)时,我得到java.lang.NoClassDefFoundError: "what version"

所以下面的测试失败了,因为你可以在最后一行看到,Apache Exec 正在生成后一个版本,而它应该生成第一个版本:

@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));
}

现在我想知道:

  • 这是一个错误吗?
  • 如果是这样:有没有办法绕过这个问题(解决方法)?
  • 如果不是:我做错了什么?

编辑:我正在尝试执行一个我认为最少人会在他们的机器上进行的过程。所以我改用java,因为这个命令应该在人们开发Java的所有机器上都可用。我的观点是错误的运行时参数被传递给外部进程,包含转义的引号,这是不应该的。

编辑:我在 Jira 为 commons exec 提交了这个 bug。

【问题讨论】:

    标签: java apache-commons-exec


    【解决方案1】:

    你可以试试下一个对我有用的例子:

      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);
    

    【讨论】:

      【解决方案2】:

      Apache common exec 具有带有handleQuoting 标志的addArgument 方法。 如果已打开,则将参数用引号括起来。

      默认开启

      public CommandLine addArgument(final String argument, boolean handleQuoting) 
      

      【讨论】:

        【解决方案3】:

        这似乎是 Apache Commons Exec 中的 real bug,迄今为止尚未修复。

        【讨论】:

        • 难以置信,这还没有得到解决——没有人使用 commons-exec 和实际需要引用的参数吗?
        • @Miles commons-exec 在引用方面非常糟糕,没有人会修复它。鉴于缺乏替代品,我也很困惑为什么没有人使用 commons-exec。每个人都真的 RYO 破坏了 ProcessBuilder 包装器吗?说到这里,为什么 ProcessBuilder 一开始就没有正确设计呢?也许没有人使用 Java 来生成进程?
        【解决方案4】:

        你想执行什么类?您没有确切指定您希望 Java 执行什么。这需要成为你的第二个论点。

        换句话说,如果您尝试运行 com.mycompany.MyExecutable,您的代码应如下所示:

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

        您可以在创建 CommandLine 对象后附加参数。

        【讨论】:

        • 您好,感谢您的回答。实际上,我不是在尝试执行 Java 类,而是完全不同的过程。但由于这是非常具体的,我不想为此编写测试用例,因为我认为没有人在他的机器上拥有这个。另一方面,每个谈论 Java 的人都在他的机器上安装了java,因此这个测试用例......
        【解决方案5】:

        像在tutorial 中那样尝试一下,看看会不会有什么不同?

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

        【讨论】:

        • 这根本不起作用,因为 Apache Commons Exec 正确地将这两个词视为单独的参数,因为它们用空格分隔。但就我而言,我需要一个包含空格的参数......但无论如何,感谢您的输入。
        猜你喜欢
        • 1970-01-01
        • 2023-03-11
        • 1970-01-01
        • 2015-06-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多