Ruby on Linux PTY在没有EOF的情况下消失,引发了Errno :: EIO

vox*_*uro 14 ruby debian pty ruby-1.9.3

我正在编写一些带有文件的代码,将该文件传递给多个二进制文件之一进行处理,并监视转换过程中的错误.我已经在OSX上编写并测试了以下例程,但linux因为我不清楚的原因而失败了.

#run the command, capture the output so it doesn't display
PTY.spawn(command) {|r,w,pid|
    until r.eof? do
      ##mark
      puts r.readline
    end
}
Run Code Online (Sandbox Code Playgroud)

运行的命令变化很大,##标记处的代码已简化为本地回显以尝试调试问题.该命令执行,脚本在终端中打印预期的输出,然后抛出异常.

它在Debian系统上产生的错误是: Errno::EIO (Input/output error - /dev/pts/0):

我可以提出的所有命令字符串都会产生错误,当我运行没有本地echo块的代码时,它运行得很好:

PTY.spawn(command) {|r,w,pid|}
Run Code Online (Sandbox Code Playgroud)

在任何一种情况下,命令本身执行正常,但似乎debian linux没有发送eof up the pty.PTY文档页面和ruby-doc上的IO似乎没有任何帮助.

有什么建议?谢谢.

-vox-

vox*_*uro 17

因此,我必须尽量读取PTY库的C源,以便对此处发生的事情感到非常满意.

Ruby PTY文档并没有真正说明源代码中的注释所说的内容.

我的解决方案是组合一个包装器方法,并在需要时从我的脚本调用它.我还装入等待进程的方法,以确保退出并从以下位置访问退出状态$?:

# file: lib/safe_pty.rb

require 'pty'
module SafePty
  def self.spawn command, &block

    PTY.spawn(command) do |r,w,p|
      begin
        yield r,w,p
      rescue Errno::EIO
      ensure
        Process.wait p
      end
    end

    $?.exitstatus
  end
end
Run Code Online (Sandbox Code Playgroud)

这与PTY.spawn基本相同:

require 'safe_pty'
exit_status = SafePty.spawn(command) do |r,w,pid|
  until r.eof? do
    logger.debug r.readline
  end
end

#test exit_status for zeroness
Run Code Online (Sandbox Code Playgroud)

我有点沮丧地发现这是一个有效的回复,因为它在ruby-doc上完全没有记录.


Ric*_*ond 5

在这里提出Errno :: EIO似乎是有效的(它只是意味着子进程已经完成并关闭了流),所以你应该期待并抓住它.

例如,请参阅Ruby中外部流程的STDOUT连续读取的选定答案和http://www.shanison.com/2010/09/11/ptychildexited-exception-and-ptys-exit-status/

顺便说一下,我做了一些测试.在Ubuntu 10.04上的Ruby 1.8.7上,我没有收到错误.使用Ruby 1.9.3,我做到了.在1.8和1.9模式的Ubuntu上使用JRuby 1.6.4,我没有收到错误.在OS X上,1.8.7,1.9.2和1.9.3,我没有收到错误.这种行为显然取决于您的Ruby版本和平台.