我正在写一些代码,需要一个文件,通过该文件的几个二进制文件进行处理的一个,并监控错误的转换过程。 我已经写了并测试了以下程序上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-
因此,我不得不去尽可能阅读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无证。
这似乎适用于在这里提出的变量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版本和平台。
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”刷新