【问题标题】:Java Runtime exec() fails to escape characters properlyJava Runtime exec() 无法正确转义字符
【发布时间】:2011-08-23 14:33:20
【问题描述】:

这可能以前已经回答过,但那是关于 unicode 的,我认为这不是 unicode(它是 ASCII 所以......)。

当我在终端中执行此操作时,没有任何问题

vboxmanage setextradata "Test Machine" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/ssh/HostPort" 2222

但是当我在 Java 中使用以下内容时

Runtime.getRuntime().exec("vboxmanage setextradata \"Test Machine\" \"VBoxInternal/Devices/pcnet/0/LUN#0/Config/ssh/HostPort\" 2222");

返回错误:未注册的 vm '"TestMachine"'

对于像Test\ Machine这样的带有空格的参数也是如此,然后它不会转义空格。

现在我认为这与字符编码有关,但我没有看到任何设置 o_O 的选项

【问题讨论】:

  • 看起来不像是编码问题。请参阅ProcessBuilder,了解如何为程序指定参数。
  • 为什么TestMachine 需要加引号或转义?
  • 因为这是在一个通用函数内部,并且有可能会有带空格的VM名称,因此我们需要引号。我会更改它以使其更清晰。

标签: java character-encoding escaping exec runtime.exec


【解决方案1】:

在这种情况下使用Runtime.exec(String) 是错误的方法(通常是向新进程传递参数的错误方法)。

使用带有参数数组的one of the exec overloads传递给新进程。 (或者,请参阅 Paul 对 ProcessBuilder 的回答——这些方法都不会出现转义问题)。

例子:

exec(new String[] { "vbomanager",
  "setextradata", "Test Machine",
  "VBoxInternal/Devices/pcnet/0/LUN#0/Config/ssh/HostPort", "2222"});

编码愉快。

【讨论】:

  • 可怕,你和我刚刚输入(几乎)相同的代码示例。我知道这是因为它是“正确”的答案,但它仍然让我回过神来。
【解决方案2】:

与其尝试引用命令行,不如使用ProcessBuilder.command(arg0, arg1, ...)

详情请见ProcessBuilder。

【讨论】:

    【解决方案3】:

    您正在一次调用程序及其参数,这有效地将整个字符串推入处理环境(希望是最好的)。

    在 Windows 系统中,操作系统强调以不同方式处理可执行文件和参数,并将它们全部放在同一个字符串中只需要您选择环境中的完美字符串(其中有两个我知道) 可以重新解析为参数列表。更好的解决方案是使用

    Runtime.exec(new String[] {"vboxmanage", "setextradata", "Test Machine", "VBoxInternal/Devices/pcnet/0/LUN#0/Config/ssh/HostPort", "2222"});
    

    对应Runtime's

    public Process exec(String[] cmdarray)
             throws IOException
    

    充其量,使用一个字符串方法,您最终会发现如何提示和转义参数,因此它们不会被视为可执行文件名称的一部分,但随后您会遇到一个新问题,即它们全部作为一个参数传递给可执行文件。一旦你根据环境修复了这个问题,你会发现你的引号没有从参数中删除(导致像“2222”这样的参数),或者 Window 的半断参数解析将首先解析空格(导致像 ("Test) 这样的参数。这没有意义,这就是为什么有多个exec 方法可用。

    【讨论】:

    • 感谢您的精彩补充:)
    • 很遗憾,使用 Runtime.exec 或 ProcessBuilder 的“分块”接口的解决方案都不适用于我的特定场景。我从配置中(来自用户)接收到整个命令行,并且我应该在执行之前替换其中的变量。示例:sometool -i ${current_file_path}。我有责任确保路径变量扩展为单个和整个命令行参数,但我不能(被打扰)解析整个命令行,因此我可以将它提供给那些分块的 API。
    【解决方案4】:

    在 Windows 上,Runtime.exec(String[]) 也是不安全的。如果参数数组包含空字符串,则空参数基本上会被省略,这可能会导致命令行无效。此外,任何参数中的引号都不带有反斜杠前缀。此外,ProcessBuilder 可以在参数中添加引号,而不会将前面的反斜杠数量加倍,如果将路径传递到包含尾随反斜杠的文件夹(如 c:\program files\),则会产生有趣的结果。

    Microsoft 的命令行标记器文档可在此处获得: http://msdn.microsoft.com/en-us/library/a1y7w461.aspx

    我描述的问题记录在这里: http://bugs.sun.com/view_bug.do?bug_id=6468220 和 http://bugs.sun.com/view_bug.do?bug_id=6518827

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-22
      • 1970-01-01
      • 1970-01-01
      • 2014-04-27
      • 1970-01-01
      • 2011-01-05
      相关资源
      最近更新 更多