红宝石在Linux上PTY消失无EOF,提高errno的:: EIO(Ruby on Linux P

2019-06-23 19:32发布

我正在写一些代码,需要一个文件,通过该文件的几个二进制文件进行处理的一个,并监控错误的转换过程。 我已经写了并测试了以下程序上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
}

运行该命令改变了很多,并在##关口的代码已经被简化为一个本地回显,试图调试问题。 命令执行和脚本打印在该终端的预期输出,然后抛出异常。

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

所有的命令字符串,我可以拿出产生的错误,当我没有地方回声块运行的代码它运行得很好:

PTY.spawn(command) {|r,w,pid|}

在这两种情况下,命令本身执行罚款,但它似乎像Debian的Linux是不发送EOF了PTY。 似乎该文档页面的PTY和IO上的红宝石DOC不要在这里借给任何援助。

有什么建议? 谢谢。

-vox-

Answer 1:

因此,我不得不去尽可能阅读C源的PTY库得到真正满意的是什么怎么回事。

红宝石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

这是使用基本相同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

我是一个多一点沮丧地发现,这是一个有效的响应,因为它是完全靠红宝石DOC无证。



Answer 2:

这似乎适用于在这里提出的变量Errno :: EIO(它只是意味着子进程已经完成,并关闭了流),所以你应该想到的是,赶上它。

例如,参照所选择的答案在连续地从外部进程的STDOUT Ruby中读和http://www.shanison.com/2010/09/11/ptychildexited-exception-and-ptys-exit-status/

顺便说一句,我做了一些测试。 在Ubuntu的10.04的Ruby 1.8.7,我没有得到一个错误。 使用Ruby 1.9.3,我做的。 通过JRuby在这两个1.8和1.9模式在Ubuntu 1.6.4,我没有得到一个错误。 在OS X上,与1.8.7,1.9.2和1.9.3,我没有得到一个错误。 该行为显然是依赖于你的Ruby版本和平台。



Answer 3:

ruby-doc.org此说,因为红宝石1.9:

# The result of read operation when pty slave is closed is platform
# dependent.
ret = begin
        m.gets          # FreeBSD returns nil.
      rescue Errno::EIO # GNU/Linux raises EIO.
        nil
      end

好了,现在我得到这样的行为是在Linux上“正常”,但是这意味着它是一个有点棘手得到PTY的输出。 如果你这样做m.read它读取的一切,那么它扔了出去,并提出errno的:: EIO。 你真的需要通过用大块阅读内容块m.readline 。 即使如此,你可能会失去的最后一行,如果它不为“\ n”无论出于何种原因结束。 为了更加安全,你需要按字节与阅读的内容字节m.read(1)

关于TTY和PTY的缓冲效果附加说明:这是不一样的STDOUT.sync = true (非缓冲输出)的子进程,而是触发线的缓冲 ,在输出的“\ n”刷新



文章来源: Ruby on Linux PTY goes away without EOF, raises Errno::EIO