Как дождаться завершения процесса с использованием IO.popen?

Я использую IO.popen в Ruby для запуска ряда команд командной строки в цикле. Затем мне нужно запустить другую команду за пределами цикла. Команда за пределами цикла не может работать до тех пор, пока все команды в цикле не будут завершены.

Как заставить программу ждать, пока это произойдет? В настоящий момент последняя команда запускается слишком быстро.

Пример:

for foo in bar
    IO.popen(cmd_foo)
end
IO.popen(another_cmd)

Таким образом, все cmd_foos должны возвращаться до запуска another_cmd.

Ответ 1

Я думаю, вам нужно будет назначить результаты из вызовов IO.popen в цикле для переменных и продолжать называть read() на них, пока eof() не станет истинным для всех.

Затем вы знаете, что все программы завершили свое исполнение, и вы можете запустить another_cmd.

Ответ 2

Используйте форму блока и прочитайте все содержимое:

IO.popen "cmd" do |io|
  # 1 array
  io.readlines

  # alternative, 1 big String
  io.read

  # or, if you have to do something with the output
  io.each do |line|
    puts line
  end

  # if you just want to ignore the output, I'd do
  io.each {||}
end

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

Ответ 3

По-видимому, canonical way для этого:

 Process.wait(popened_io.pid)

Ответ 4

for foo in bar
  out = IO.popen(cmd_foo)
  out.readlines
end
IO.popen(another_cmd)

Чтение вывода на переменную, а затем вызов out.readlines сделал. Я думаю, что out.readlines должен ждать завершения процесса до его возвращения.

Благодарим Эндрю Y за то, что указали мне в правильном направлении.

Ответ 5

Я предлагаю вам использовать Thread.join для синхронизации последнего вызова popen:

t = Thread.new do
    for foo in bar
       IO.popen(cmd_foo)
    end
end

t.join

IO.popen(another_cmd)

Ответ 6

Вам нужен вывод popen? Если нет, вы хотите использовать Kernel#system или какую-либо другую команду?