【问题标题】:Executing untokenized command line from Java从 Java 执行未标记的命令行
【发布时间】:2009-12-30 15:16:23
【问题描述】:

我目前正在使用 ProcessBuilder 从 Java 服务器运行命令。该服务器将替换旧的 Perl 服务器,我们的许多遗留代码都指定了特定于平台的命令行。

例如,在 Windows 上它可能会这样做:

command -option "hello world"

在 unix 上它可能会这样做:

command -option 'hello world'

问题是 ProcessBuilder 和 Runtime.exec 都接受标记化的命令行(例如,对于 unix 和 windows,{"command", "-option", "hello world"})。

虽然我更喜欢平台无关的方式,但我们的代码库中有大约 3000 万行 perl 代码。如果没有我为不同平台编写标记器(真的没什么大不了,我只是不想制作 WTF),有没有办法让操作系统上的 shell 标记命令行?

【问题讨论】:

  • command -option "hello world" 也适用于 unix,引号就是引号...
  • 不管怎样,我们的代码确实在 windows 和 unix 上进行了条件化,通常是因为命令比这更复杂,并且有嵌套的引号和命令行变量以及其他类似的废话。
  • 3000 万行 perl?!?我很高兴我不是你;)

标签: java command-line


【解决方案1】:

您能否使用重载的Runtime.exec(String),它接受单个字符串并将其作为整个命令运行?


以下内容适用于 Windows:

Process p = Runtime.getRuntime().exec("perl -e \"print 5\"");
System.out.println(IOUtils.toString(p.getInputStream()));
p.destroy();

这或多或少是 Runtime.exec(String) 正在做的事情:

public static void main(String [] args) throws Exception {
    Process p = new ProcessBuilder(getCommand("perl -e \"print 5\"")).start();
    System.out.println(IOUtils.toString(p.getInputStream()));
    p.destroy();

}

private static String[] getCommand(String input) {
    StringTokenizer tokenizer = new StringTokenizer(input);
    String[] result = new String[tokenizer.countTokens()];
    for (int i = 0; tokenizer.hasMoreTokens(); i++) {
        result[i] = tokenizer.nextToken();
    }
    return result;
}

【讨论】:

  • Perl 是否在进程正在执行的环境的路径上?
  • 糟糕,我刚刚意识到我使用的是 ProcessBuilder,而不是 Runtime.exec()。
  • 无论如何使用 Runtime.exec() 而不失去将标准错误重定向到标准输出的能力?
  • 看起来不是这样。但是,如果您深入了解 Runtime.exec(String),您会发现它只是使用 StringTokenizer 将参数解析为数组,然后将其传递给 ProcessBuilder。也许你可以做类似的事情
【解决方案2】:

我认为引号是由 shell 解释的。而是将命令放在 shell 脚本中:

$ cat temp.sh 
#!/bin/sh
perl -e "print 5"

并执行它:

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class PBTest {

    public static void main(String[] args) {
        ProcessBuilder pb = new ProcessBuilder("./temp.sh");
        pb.redirectErrorStream(true);
        try {
            Process p = pb.start();
            String s;
            BufferedReader stdout = new BufferedReader (
                new InputStreamReader(p.getInputStream()));
            while ((s = stdout.readLine()) != null) {
                System.out.println(s);
            }
            System.out.println("Exit value: " + p.waitFor());
            p.getInputStream().close();
            p.getOutputStream().close();
            p.getErrorStream().close();
         } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

控制台:

5
Exit value: 0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-23
    • 2013-08-25
    • 2017-10-07
    • 2011-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多