我写了一个雷神脚本运行一些测试从不同的工具,即。运行shell命令。我希望命令中的stdout和stderr不断地输出到我的控制台。
第一次尝试是只使用反引号,但自然不会打印stdout/stderr(而是在返回值中捕获stdout)。
desc "mytask", "my description"
def mytask
`run-my-tests.sh`
end
我的下一个方法是使用Open 3,如下所示:
require "open3"
desc "mytask", "my description"
def mytask
Open3.popen3("run-my-tests.sh") do |stdin, stdout, stderr|
STDOUT.puts(stdout.read())
STDERR.puts(stderr.read())
end
end
但是,上述方法将从stdout和stderr获得整个输出,并且只在最后打印。在我的用例中,我宁愿看到失败和通过测试的输出,因为它变得可用。
从http://blog.bigbinary.com/2012/10/18/backtick-system-exec-in-ruby.html中,我看到我们可以按块读取流,即用gets()
代替read()
。例如:
require "open3"
desc "mytask", "my description"
def mytask
Open3.popen3(command) do |stdin, stdout, stderr|
while (out = stdout.gets()) || err = (stderr.gets())
STDOUT.print(out) if out
STDERR.print(err) if err
end
exit_code = wait_thr.value
unless exit_code.success?
raise "Failure"
end
end
end
它看起来像是最好和最干净的方法吗?我必须手动尝试在 * stderr之前打印stdout *,这是一个问题吗?
3条答案
按热度按时间rqdpfwrv1#
我使用
IO.popen
来完成类似的任务,如下所示:IO.popen([env, *command]) do |io| io.each { |line| puts ">>> #{line}" } end
要捕获stderr,我只需将其重定向到stdoutcommand = %w(run-my-tests.sh 2>&1)
更新我使用
Open3::popen3
构建了一个脚本来分别捕获stdout和stderr。它显然有很大的改进空间,但基本的想法希望是明确的。vmdwslir2#
在我看来,运行shell命令并 * 不 * 尝试捕获stdout或stderr(相反,让它们在出现时冒泡)的最简单方法是:
反向标记或
system()
的问题在于前者捕获stdout,后者只返回命令是否成功。spawn()
是system()
的一个更有用的替代方案。我宁愿我的Thor脚本工具失败,就好像它只是那些shell命令的 Package 器一样。svdrlsy43#
如果你在这里结束,因为你只是想在错误时失败,你可以添加
abort_on_failure: true
选项到run
命令,如下所示: