如何使管道与Runtime.exec()一起工作?

pou*_*def 101 java exec runtime.exec

请考虑以下代码:

String commandf = "ls /etc | grep release";

try {

    // Execute the command and wait for it to complete
    Process child = Runtime.getRuntime().exec(commandf);
    child.waitFor();

    // Print the first 16 bytes of its output
    InputStream i = child.getInputStream();
    byte[] b = new byte[16];
    i.read(b, 0, b.length); 
    System.out.println(new String(b));

} catch (IOException e) {
    e.printStackTrace();
    System.exit(-1);
}
Run Code Online (Sandbox Code Playgroud)

该程序的输出是:

/etc:
adduser.co
Run Code Online (Sandbox Code Playgroud)

当我从shell运行时,它当然按预期工作:

poundifdef@parker:~/rabbit_test$ ls /etc | grep release
lsb-release
Run Code Online (Sandbox Code Playgroud)

互联网告诉我,由于管道行为不是跨平台的事实,在Java工厂生产Java的杰出人才无法保证管道工作.

我怎样才能做到这一点?

我不会做所有使用Java构建,而不是我的解析grepsed,因为如果我想改变的语言,我将被迫在语言,这完全是一个没有去重新写我的解析代码.

在调用shell命令时如何让Java进行管道和重定向?

Kaj*_*Kaj 176

编写脚本,然后执行脚本而不是单独的命令.

管道是shell的一部分,所以你也可以这样做:

String[] cmd = {
"/bin/sh",
"-c",
"ls /etc | grep release"
};

Process p = Runtime.getRuntime().exec(cmd);
Run Code Online (Sandbox Code Playgroud)

  • @Kaj我看到你正在尝试使用-c为shell指定一串命令,但是我不明白为什么你要把它变成一个字符串数组而不是一个字符串呢? (7认同)
  • 如果有人在这里寻找 `android` 版本,那么使用 `/system/bin/sh` 代替 (3认同)

Tih*_*mer 24

我在Linux中遇到了类似的问题,除了它是"ps -ef | grep someprocess".
至少使用"ls",您可以使用与语言无关(尽管速度较慢)的Java替换.例如.:

File f = new File("C:\\");
String[] files = f.listFiles(new File("/home/tihamer"));
for (String file : files) {
    if (file.matches(.*some.*)) { System.out.println(file); }
}
Run Code Online (Sandbox Code Playgroud)

使用"ps",它有点难,因为Java似乎没有它的API.

我听说Sigar可以帮助我们:https: //support.hyperic.com/display/SIGAR/Home

然而,最简单的解决方案(如Kaj所指出的)是将piped命令作为字符串数组执行.这是完整的代码:

try {
    String line;
    String[] cmd = { "/bin/sh", "-c", "ps -ef | grep export" };
    Process p = Runtime.getRuntime().exec(cmd);
    BufferedReader in =
            new BufferedReader(new InputStreamReader(p.getInputStream()));
    while ((line = in.readLine()) != null) {
        System.out.println(line); 
    }
    in.close();
} catch (Exception ex) {
    ex.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)

至于为什么String数组使用管道,而单个字符串不...它是宇宙的奥秘之一(特别是如果你还没有阅读源代码).我怀疑这是因为当exec被赋予一个字符串时,它首先解析它(以我们不喜欢的方式).相反,当给exec一个字符串数组时,它只是将它传递给操作系统而不解析它.

实际上,如果我们从繁忙的一天中抽出时间并查看源代码(请访问http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/ Runtime.java#Runtime.exec%28java.lang.String%2Cjava.lang.String []%2Cjava.io.File%29),我们发现这正是发生的事情:

public Process  [More ...] exec(String command, String[] envp, File dir) 
          throws IOException {
    if (command.length() == 0)
        throw new IllegalArgumentException("Empty command");
    StringTokenizer st = new StringTokenizer(command);
    String[] cmdarray = new String[st.countTokens()];
    for (int i = 0; st.hasMoreTokens(); i++)
        cmdarray[i] = st.nextToken();
    return exec(cmdarray, envp, dir);
}
Run Code Online (Sandbox Code Playgroud)


SJu*_*n76 6

创建运行时以运行每个进程.从第一个运行时获取OutputStream,并将其从第二个运行时复制到InputStream中.