如何在ruby19中替换STDIN,STDOUT,STDERR

时间:2012-02-15 11:26:19

标签: ruby fork stdin dup

在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中不起作用。 STDIN,STDOUT,STDERR的close方法不会关闭ruby19中的底层文件描述符。我如何在ruby19中执行此操作。

2 个答案:

答案 0 :(得分:1)

查看Process.spawnOpen3childprocess gem。

我无法准确说出你在那里做了什么,但是你可以通过多种方式控制子进程的IO。

使用Unix管道:

readme, writeme = IO.pipe
pid = fork {
    $stdout.reopen writeme
    readme.close
    exec(...)
}

使用Process.spawn

来处理IO
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

您可能还会考虑Jesse Storimer的 Working With Unix Processes 。它有很多信息,他的写作风格很容易阅读和理解。这本书兼作参考指南,它比许多实际文档更有用。


参考:

答案 1 :(得分:0)

This post显示了在Ruby中暂时替换stdin的一种方法:

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

由于这个问题是“ruby replace stdin”的热门谷歌热门之一,我希望这会帮助其他人寻找如何做到这一点。