Groovy管道是真正的UNIX管道吗?

时间:2011-07-11 16:46:42

标签: groovy

我今天刚开始研究Groovy。我考虑使用它来替换一些更复杂的bash脚本。

对我来说,其中一个非常有趣的概念是use pipes easily的可能性:

proc1 = 'ls'.execute()
proc2 = 'tr -d o'.execute()
proc3 = 'tr -d e'.execute()
proc4 = 'tr -d i'.execute()
proc1 | proc2 | proc3 | proc4
proc4.waitFor()

太棒了。但我的问题是:这是否使用真正的UNIX管道(例如在Linux上运行时),或者这只是一个使用Java流的模拟? (如果是这样,它会慢得多/效率低吗?)

3 个答案:

答案 0 :(得分:6)

由于运算符重载,它最终在Groovy运行时调用ProcessGroovyMethods.pipeTo(),它确实使用java流模拟管道:

    /**
     * Allows one Process to asynchronously pipe data to another Process.
     *
     * @param left  a Process instance
     * @param right a Process to pipe output to
     * @return the second Process to allow chaining
     * @throws java.io.IOException if an IOException occurs.
     * @since 1.5.2
     */
    public static Process pipeTo(final Process left, final Process right) throws IOException {
        new Thread(new Runnable() {
            public void run() {
                InputStream in = new BufferedInputStream(getIn(left));
                OutputStream out = new BufferedOutputStream(getOut(right));
                byte[] buf = new byte[8192];
                int next;
                try {
                    while ((next = in.read(buf)) != -1) {
                        out.write(buf, 0, next);
                    }
                } catch (IOException e) {
                    throw new GroovyRuntimeException("exception while reading process stream", e);
                } finally {
                    closeWithWarning(out);
                }
            }
        }).start();
        return right;
    }

我无法谈论我头顶的开销量。

答案 1 :(得分:5)

我发现groovy管道模拟比unix管道慢得多:

Bash命令

zcat dump.sql.gz | mysql -u${mysql_user} --password=${mysql_password} -D${db_name} 

大约需要40分钟

与groovy相同的事情

def proc1 = ["zcat", "${sqlGzFile.getPath()}"].execute()
def proc2 = ["mysql", "-u${mysqlUser}", "--password=${mysqlPassword}", "-D$dbName"].execute()   
proc1 | proc2
proc2.waitFor()

大约需要2小时40分钟

但你可以用:

做管道
def proc = ["sh", "-c",  "zcat dump.sql.gz | mysql -u${mysql_user} --password=${mysql_password} -D${db_name}"].execute()
proc.waitFor()

答案 2 :(得分:2)

Groovy不能使用Unix管道,因为在子进程启动之前必须先设置的Unix管道。但是您的示例首先启动所有进程并将它们与管道以后连接

Groovy也必须调用一些文件句柄操作系统调用(dupdup2),这些调用在JVM中不可用而不使用其他一些本机库。