Java getRuntime Exec

Java getRuntime Exec,java,exec,runtime.exec,Java,Exec,Runtime.exec,我正在Java 1.8上调用p=Runtime.getRuntime().exec(命令)。 该命令调用bash脚本,如下所示: #!/bin/bash args=("$@") cat /home/user/Downloads/bigtext.txt | grep ${args[0]} 上面的bash脚本在使用命令行调用时工作正常。在Java应用程序中使用exec()调用时,不会返回CAT输出。它似乎没有通过p.waitFor();我哪里做错了 如果我直接运行一个命令,比如“ls-alF”,那

我正在Java 1.8上调用p=Runtime.getRuntime().exec(命令)。 该命令调用bash脚本,如下所示:

#!/bin/bash
args=("$@")
cat /home/user/Downloads/bigtext.txt | grep ${args[0]}
上面的bash脚本在使用命令行调用时工作正常。在Java应用程序中使用exec()调用时,不会返回CAT输出。它似乎没有通过p.waitFor();我哪里做错了

如果我直接运行一个命令,比如“ls-alF”,那么一切都会按预期工作

$ java -version java version "1.8.0_31" Java(TM) SE Runtime Environment (build 1.8.0_31-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)


String tmp = "/home/user/search "+input;        
System.out.println(tmp); //  /home/user/search sometextarg
String woa = executeCommand(tmp);


private String executeCommand(String command) {     
        StringBuilder output = new StringBuilder();
                BufferedReader reader = null;
        Process p;
        try {
            p = Runtime.getRuntime().exec(command);
            p.waitFor();

                        reader = new BufferedReader(new InputStreamReader(p.getInputStream()));

            String line = "";

            while ((line = reader.readLine())!= null) {
                output.append(line + "\n");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return output.toString();
    }

您的Java进程和脚本彼此处于死锁状态:您在等待进程退出,进程在等待您读取输出

它恰好适用于
ls-alF
和其他输出较小的命令,因为它们都适合管道的缓冲区(在我的系统上是64kib)

只需将
p.waitFor()
移动到while循环下方,您就会有更多的运气:

private String executeCommand(String command) {     
    StringBuilder output = new StringBuilder();
            BufferedReader reader = null;
    Process p;
    try {
        p = Runtime.getRuntime().exec(command);
        reader = new BufferedReader(new InputStreamReader(p.getInputStream()));

        String line = "";
        while ((line = reader.readLine())!= null) {
            output.append(line + "\n");
        }
        p.waitFor();

    } catch (Exception e) {
        e.printStackTrace();
    }
    return output.toString();
}
如果您还希望它能正确处理包含空格和某些其他字符的值,则必须:

  • 在脚本中引用
    “${args[0]}”
  • 重写
    executeCommand
    以使用
    Runtime.exec(String[])
    而不是
    Runtime.exec(String)

  • 正在等待你读取输出,你能解释一下吗?@SotiriosDelimanolis你的脚本可以写数据,比你的Java程序读取数据快得多。然而,这并不是因为它没有尽可能快地推送数据,完全压倒Java程序,而是脚本将1。写一块数据,2。等待它被读取。3.根据需要重复(管道就是这样工作的)。在你的例子中,脚本被卡在了第2步,因为你根本没有从管道中读取,而是等待程序退出。我想让你澄清的是管道是如何工作的。生成的进程不应等待Java(或任何其他进程)从其标准输出中读取。@SotiriosDelimanolis管道的缓冲区有限。当缓冲区已满时,进程在清空之前无法写入。当缓冲区为空时,进程在其填满之前无法读取。在您概述的用例中,这绝对是您想要的。如果您有一个完全不同的用例,例如工业机械控制器的严格延迟要求,请发布一个单独的问题。那么您是说问题出在
    cat/home/user/Downloads/bigtext.txt | grep${args[0]}
    livelocking,hat
    grep
    无法继续,因为
    java
    进程尚未读取其输出?有多大
    bigtext.txt
    ?你在搜索什么?它的136 Mb文本文件