我正在寻找相当于反引号运算符(``)的东西,它能够在shell命令执行期间显示输出。
我在另一篇文章中看到了一个解决方案: (Running a command from Ruby displaying and capturing the output)
output = []
IO.popen("ruby -e '3.times{|i| p i; sleep 1}'").each do |line|
p line.chomp
output << line.chomp
end
p output
此解决方案不符合我的需求,因为$? shell命令执行后仍为零。我正在寻找的解决方案也应该设置$? (以另一种方式返回$ ?. exitstatus的值也足够了)
谢谢!
答案 0 :(得分:4)
首先,我建议使用Open3中的一种方法。
我对我的一个系统使用capture3
,我们需要获取许多命令行应用程序的STDOUT和STDERR的输出。
如果您需要管道子流程,请尝试popen3
或其他“管道”命令之一。
这里有一些代码来说明如何使用忽略STDERR通道的popen2
。如果您想跟踪它,也请使用popen3
:
require 'open3'
output = []
exit_status = Open3.popen2(ENV, "ruby -e '3.times{|i| p i; sleep 1}'") { |stdin, stdout, thr|
stdin.close
stdout.each_line do |o|
o.chomp!
output << o
puts %Q(Read from pipe: "#{ o }")
end
thr.value
}
puts "Output array: #{ output.join(', ') }"
puts "Exit status: #{ exit_status }"
运行输出:
Read from pipe: "0"
Read from pipe: "1"
Read from pipe: "2"
Output array: 0, 1, 2
Exit status: pid 43413 exit 0
示例代码显示一种方式。
没有必要使用each_line
,但这证明了如何逐行读取,直到子流程关闭其STDOUT。
capture3
不接受任何阻止;它等待孩子关闭其输出并退出,然后返回内容,这在您想要阻止过程时很有用。 popen2
和popen3
具有阻止和非阻止版本,但我在此处仅显示非阻止版本,以演示如何从子流程中读取和输出内容。
答案 1 :(得分:3)
请尝试以下操作:
output = []
IO.popen("ruby -e '3.times{|i| p i; sleep 1 }'") do |f|
f.each do |line|
p line.chomp
output << line.chomp
end
end
p $?
打印
"0"
"1"
"2"
#<Process::Status: pid 2501 exit 0>
使用open3
require 'open3'
output = []
Open3.popen2("ruby -e '3.times{|i| p i; sleep 1}'") do |stdin,stdout,wait_thr|
stdout.each do |line|
p line.chomp
output << line.chomp
end
p wait_thr.value
end