Как заменить STDIN, STDOUT, STDERR в ruby19
В ruby18 я иногда делал следующее, чтобы получить подпроцесс с полным контролем:
stdin, @stdin= IO.pipe
@stdout, stdout= IO.pipe
@stderr, stderr= IO.pipe
@pid= fork do
@stdin.close
STDIN.close
stdin.dup
@stdout.close
STDOUT.close
stdout.dup
@stderr.close
STDERR.close
stderr.dup
exec(...)
end
Это не работает в ruby19. Метод close для STDIN, STDOUT, STDERR не закрывает основной файловый дескриптор в ruby19. Как мне это сделать в ruby19.
2 ответа
Этот пост показывает один способ временно заменить стандартный ввод в Ruby:
begin
save_stdin = $stdin # a dup by any other name
$stdin.reopen('/dev/null') # dup2, essentially
# do stuff
ensure
$stdin.reopen(save_stdin) # restore original $stdout
save_stdin.close # and dispose of the copy
end
Поскольку этот вопрос является одним из самых популярных в Google по запросу "ruby replace stdin", я надеюсь, что это поможет другим, ищущим, как это сделать.
Проверять, выписываться Process.spawn
, Open3
и childprocess
драгоценный камень.
Я не могу точно сказать, что вы пытаетесь сделать там, но вы можете контролировать IO дочернего процесса разными способами.
Использование каналов Unix:
readme, writeme = IO.pipe
pid = fork {
$stdout.reopen writeme
readme.close
exec(...)
}
Жонглирование IO с Process.spawn
:
pid = spawn(command, :err=>:out)
Или завернуть процесс в POpen3
:
require 'open3'
include Open3
popen3(RUBY, '-r', THIS_FILE, '-e', 'hello("Open3", true)') do
|stdin, stdout, stderr|
stdin.write("hello from parent")
stdin.close_write
stdout.read.split("\n").each do |line|
puts "[parent] stdout: #{line}"
end
stderr.read.split("\n").each do |line|
puts "[parent] stderr: #{line}"
end
Вы также можете рассмотреть работу Джесси Стоимера с процессами Unix. В нем много информации, и его стиль письма очень легко читать и понимать. Книга служит справочным пособием, которое несколько полезнее, чем много реальной документации.
Рекомендации: