我知道足够多的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
}
这工作正常,但会将大量输出转储到控制台,这有点妨碍了。所以我很想通过 xcpretty 来重新格式化它。
如果我实际上从我的终端运行命令,它工作正常:
xcodebuild -scheme Foo -configuration Release archive | xcpretty
但是,如果我修改 Rake 任务以仅将这些部分附加到命令数组的末尾,sh
认为它们是xcodebuild
的参数。
command.push "archive", "|", "xcpretty"
我已经看到许多示例将sh
与字符串形式的管道一起使用,但不是数组形式。由于我正在构建的命令的性质(可选参数、带空格的参数和其他字符),数组形式处理起来要干净得多。但是有没有办法在使用时包括输出管道?
一个好的解决方案是使用 Open3,这是 Ruby 的标准部分,它有很多用于打开进程和安排管道的实用程序。
这是一个对我有用的例子:
require 'open3'
Open3.pipeline(['ls', '-l'], ['grep', 'z'])
运行此操作时,管道中最后一个命令的标准输出管道将连接到 Ruby 进程的预先存在的标准输出管道。 这意味着您将能够在生成任何输出时立即看到它,而不是等待流程结束。 此方法的另一个好处是它不会生成外壳;它只是直接生成进程。
另一种选择是简单地使用 Array#join 将参数与空格连接在一起,然后再将它们传递给 sh
。 你只需要注意你的论点可能有空格的可能性,如果是这样,那么你必须正确地引用或转义它们。 此方法将生成一个 shell 来处理您的命令,它还应该为长时间运行的进程提供即时输出。