2013-08-22 2 views
2

Я ищу что-то эквивалентное оператору backticks (``) с возможностью отображения вывода во время выполнения команды оболочки.эквивалент оператора backticks с возможностью отображения вывода во время выполнения

я увидел решение в другом посте: (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 

Это решение не соответствует моим потребностям, так как $? остается без изменений после выполнения команды оболочки. Решение, которое я ищу, также должно установить $? (также необходимо указать значение $ ?. exitstatus по-другому)

Спасибо!

ответ

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 
4

Во-первых, я бы рекомендовал использовать один из методов в Open3.

Я использую capture3 для одной из моих систем, где нам нужно захватить выходные данные STDOUT и STDERR из множества приложений с командной строкой.

Если вам нужен подпроцесс с трубопроводом, попробуйте popen3 или одну из других команд «конвейер».

Вот код, который иллюстрирует использование popen2, который игнорирует канал STDERR. Если вы хотите, чтобы отслеживать, что также использовать 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 имеют блокирующие и неблокирующие версии, но здесь я показываю только неблокирующую версию, чтобы продемонстрировать, как читать и выводить контент, как он поступает из подпроцесса.

+0

Можете ли вы поместить код, который выполняет ту же задачу выше, используя capture3 (и два разных массива)? – miluz

+0

Ваш код не имеет двух разных массивов, он имеет только один. –

Смежные вопросы