Запуск команды оболочки из Ruby: захватить вывод при отображении вывода? - PullRequest
5 голосов
/ 10 сентября 2010

У меня проблема.

Я хочу запустить скрипт ruby ​​из другого скрипта ruby ​​и захватить его выходные данные, а также вывести его на экран.

Финалист

#!/usr/bin/env ruby
print "Enter your password: "
password = gets.chomp
puts "Here is your password: #{password}"

Файл сценария, который я запускаю:

start.rb

output = `runner`
puts output.match(/Here is your (password: .*)/).captures[0].to_s

Как видите, здесь есть проблема.

В первой строке start.rb экран пуст.

Я не вижу "Введите ваш пароль:" в бегуне.

Есть ли способ отобразить вывод скрипта бегуна до его завершения, и все же позволить мне записать его в строку, чтобы я мог обработать информацию, например использовать совпадение как в этом примере?

Ответы [ 7 ]

7 голосов
/ 24 сентября 2010

runner.rb

STDOUT.print "Enter your password: "
password = gets.chomp
puts "Here is your password: #{password}"

Примечание STDOUT.print

start.rb

require "stringio"

buffer = StringIO.new
$stdout = buffer

require "runner"

$stdout = STDOUT
buffer.rewind

puts buffer.read.match(/Here is your (password: .*)/).captures[0].to_s

выход

Enter your password: hello
password: hello

Подробнее ...

Я недавно написал об этом здесь: Выходная буферизация с помощью Ruby

2 голосов
/ 10 сентября 2010

Попробуйте это:

rd, wr = IO::pipe
pid = Process.fork do  
  $stdout.reopen(wr)
  rd.close
  exec("command")
end
wr.close
rd.each do |line|  
  puts "line from command: #{line}"
end
Process.wait(pid)

Аналогично, если вы хотите захватить stderr . Если вам нужно захватить оба, это будет немного сложнее (Kernel.select?)

Редактировать: некоторые объяснения. Это древняя процедура Unix: pipe + fork + вызывает dup2 (открывается заново) в зависимости от того, что вы хотите. В двух словах: вы создаете канал как средство общения между ребенком и родителем. После разветвления каждый одноранговый узел закрывает конечную точку канала, которую он не использует, дочерний элемент перераспределяет (открывает заново) канал, который вам нужен, в конечную точку записи канала, и, наконец, родительский элемент читает канал чтения канала.

1 голос
/ 30 марта 2012

Для независимой от сценариев регистрации вы можете включить ее из эмулятора терминала (контейнера оболочки).screen -L ИЛИ xterm -l Это будет захватывать весь вывод, созданный любой оболочкой или программой, работающей внутри эмулятора, включая вывод, созданный вашими скриптами ruby.

0 голосов
/ 10 сентября 2010
io = IO.popen(<your command here>)
log = io.readlines
io.close

Теперь в переменной журнала у вас есть вывод выполненной команды. Разберите его, конвертируйте или делайте что хотите.

0 голосов
/ 10 сентября 2010

Пусть ваш скрипт выдает подсказку в stderr.

echo "Enter something" >&2
read answer
echo "output that will be captured"

Это будет сделано для вас, если вы используете read -p для выдачи подсказки:

read -p "Enter something" answer
echo "output that will be captured"
0 голосов
/ 10 сентября 2010

Посмотрите на POpen4 .Он претендует на независимость от платформы (но я не думаю, что он работает в jruby, где вместо него можно использовать IO#popen).

0 голосов
/ 10 сентября 2010

Вы можете использовать tee , чтобы записать содержимое в файл или канал и затем прочитать файл.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...