1

在 ruby​​18 中,我有时会执行以下操作来获得完全控制的子进程:

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

这在 ruby​​19 中不起作用。STDIN、STDOUT、STDERR 的 close 方法不会关闭 ruby​​19 中的底层文件描述符。我如何在 ruby​​19 中做到这一点。

4

2 回答 2

1

查看Process.spawn,Open3childprocessgem。

我不能确切地说出你在那里尝试做什么,但你可以通过多种方式控制子进程的 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

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


参考:

于 2013-02-08T08:23:01.273 回答
1

这篇文章展示了一种在 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

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

于 2016-03-06T02:03:54.933 回答