Ruby中Kernel#select的作用是什么?

4

我正在编写一段Ruby脚本,最终要启动一个耗时较长的系统进程。我需要从该进程的stderr读取内容并根据输出做出反应。

目前我的实现方式如下:

Open3.popen3(cmd_to_run) do |stdin, stdout, stderr, waitthread|
  stderr.each_line do |line|
    # look out for specific lines and react to them accordingly
  end
end

但我也见过使用 kernel#select 实现类似功能的实现方式:

Open3.popen3(cmd_to_run) do |stdin, stdout, stderr, waitthread|
  io = select([stderr], nil, nil, 30)

  if io.nil?
    log("Command timed out during Kernel#select")
    return
  end

  io[0][0].each_line do |line|
    # look out for specific lines and react to them accordingly
  end

end

我已阅读《Ruby程序员修炼之道》中有关select的解释,但我不确定为什么要使用它(或者是否需要使用)。第一种方法看起来也能实现同样的功能。
1个回答

6

可能有两个原因:

  1. 你可以使用超时,而这在使用 each_line 时是不行的。
  2. 你可以等待多个 IO 对象,例如 io = select([stdout, stderr]),以及多个事件(例如写入事件或异常)。

我猜我不太明白为什么需要“等待”IO对象?为什么在启动进程后它们不能立即使用? - Brian
1
IO对象立即可用,但是当您尝试读取例如stdout时,如果没有任何内容(尚未),则您的监视进程将阻塞。想象一下,您的系统进程将一些诊断信息打印到stderr并等待您的回复,但它是stderr而不是stdout,因此您将永远在stdout上等待某些内容。 select从列表中返回第一个可用的IO对象,其中发生了某些事情,因此您可以处理它,并且read不会阻塞,因为有东西。 - Victor Moroz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接