使用Java Runtime exec()

时间:2015-11-13 15:10:43

标签: java linux bash runtime.exec

我正在尝试在Ubuntu 14.04上使用exec() - java.lang.Runtime方法执行的命令中使用重定向

public static void main(String[] args) throws IOException, Exception {
    Runtime runtime = Runtime.getRuntime();
    String command = "echo bla > bla.txt";
    System.out.println("Command : " + command);
    Process process = runtime.exec(command);
    printLines(" stdout", process.getInputStream());
    printLines("  error", process.getErrorStream());
    process.waitFor();
    System.out.println("ExitValue : " + process.exitValue());
}

private static void printLines(String name, InputStream ins) throws Exception {
    try(Stream<String> lines = new BufferedReader(new InputStreamReader(ins)).lines()) {
        lines.forEach(line -> System.out.println(name + " : " + line));
    }
}

输出结果为:

Command : echo bla > bla.txt
 stdout : bla > bla.txt
ExitValue : 0

因此bla > bla.txt写入stdout,但当然没有重定向到bla.txt

在简单的exec()中无法进行Perhapes shell重定向。

所以我尝试更改command = "/bin/bash -c 'echo bla > bla.txt'"以使用整个回显并将其重定向为/bin/bash

有了这个,我得到了结果:

Command : /bin/bash -c 'echo bla > bla.txt'
  error : bla: -c: line 0: unexpected EOF while looking for matching `''
  error : bla: -c: line 1: syntax error: unexpected end of file
ExitValue : 1

当然/bin/bash -c 'echo bla > bla.txt'在Ubuntu上工作正常并创建所需的文件。

我找不到可以设置单引号以获得令人满意的结果的地方,我也尝试使用各种转义字符来转义空格或重定向(>)。

如果我使用像

这样的命令数组,它就可以工作
String cmdArray[] = {"/bin/bash", "-c", "echo bla > bla.txt"};
Process process = runtime.exec(cmdArray);

,但它必须是单个字符串,因为整个命令必须在其他地方构建。

我当然知道

  • 有更好的方法可以将字符串写入文件,
  • 在其他地方执行命令构建可能是个坏主意,
  • 等......

我只是好奇为什么这不起作用。

2 个答案:

答案 0 :(得分:1)

原因是exec使用带有任何空格的简单StringTokenizer作为解析实际命令的分隔符。因此它是便携式的,因为当你传递复杂的东西时它无处可用: - )

您选择的解决方法是正确的方式,可移植且最重要的是最安全的,因为如果命令包含例如引号等,则您需要逃脱。

答案 1 :(得分:1)

else if (DSBtn.IsChecked)
...

命令中的String command = "echo bla > bla.txt"; Process process = runtime.exec(command); 文本是用于重定向标准输出的shell语法。它由> blah.txtsh等shell实现。

bash不使用shell来运行命令。它启动命令的方式是herehere。基本上,它使用自己的逻辑将命令字符串拆分为空格中的参数,然后直接执行生成的命令。

如果要调用应解释为shell命令的命令,则需要显式调用shell:

Runtime.exec()