如何在FileUtils #sh中包含一个执行命令的管道?

时间:2015-02-02 16:44:45

标签: ruby shell pipe

我知道有足够的Ruby是危险的,所以我正在编写一堆构建自动化脚本作为Rake任务,主要是通过API文档中的示例来处理。

我正在编写一堆构建命令,其代码如下:

results = {}
schemes.each { |scheme|
    command = "xcodebuild", "-scheme", scheme
    if options.configuration
        command.push "-configuration", options.configuration
    end
    command.push "archive"

    sh *command do |ok, res|
        results[scheme] = ok
    end
}

这样可以正常工作,但会将 lot 的输出转储到控制台,这样会妨碍它。因此,我希望通过xcpretty来管理这些内容以重新格式化。

如果我实际上从我的终端运行命令,它可以正常工作:

xcodebuild -scheme Foo -configuration Release archive | xcpretty

但是如果我修改Rake任务只是将这些部分附加到命令数组的末尾,sh认为它们是xcodebuild的参数。

    command.push "archive", "|", "xcpretty"

我已经看到了一些使用sh的示例,其中包含字符串形式的管道,但不是数组形式。由于命令的性质,我正在构建可选参数,带空格和其他字符的参数 - 数组形式要处理得更清晰。但使用它时是否有办法包括输出管道?

1 个答案:

答案 0 :(得分:3)

一个好的解决方案是使用Open3,这是Ruby的标准部分,它有许多用于打开流程和安排管道的实用工具。

这是一个对我有用的例子:

require 'open3'
Open3.pipeline(['ls', '-l'], ['grep', 'z'])

运行此命令时,管道中最后一个命令的标准输出管道将连接到Ruby进程的预先存在的标准输出管道。这意味着您可以在生成时立即看到任何输出,而不是等待进程结束。这种方法的另一个好处是它不会产生shell;它只是直接产生过程。

另一种选择是在将参数传递给sh之前简单地使用Array#join将参数与空格连接在一起。你只需要注意你的参数可能在其中有空格的可能性,如果是这样,那么你必须正确引用或转义它们。此方法将生成一个shell来处理您的命令,它还应该为长时间运行的进程提供即时输出。