Ale*_*ski 5 ruby io pipe popen
鉴于我希望测试从长命令非阻塞读,我创建了下面的脚本,保存为long,使其可执行文件chmod 755,并把它放在我的道路(保存~/bin/long在那里~/bin是我的路径).
我在ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-darwin11.0.0]使用RVM默认编译的*nix变体上.我不使用Windows,因此如果你这样做,我不确定测试脚本是否适合你.
#!/usr/bin/env ruby
3.times do
STDOUT.puts 'message on stdout'
STDERR.puts 'message on stderr'
sleep 1
end
Run Code Online (Sandbox Code Playgroud)
为什么long_err生成每条STDERR消息,因为它是由"long"打印的
def long_err( bash_cmd = 'long', maxlen = 4096)
stdin, stdout, stderr = Open3.popen3(bash_cmd)
begin
begin
puts 'err -> ' + stderr.read_nonblock(maxlen)
end while true
rescue IO::WaitReadable
IO.select([stderr])
retry
rescue EOFError
puts 'EOF'
end
end
Run Code Online (Sandbox Code Playgroud)
在long_out打印所有STDOUT消息之前一直被阻止?
def long_out( bash_cmd = 'long', maxlen = 4096)
stdin, stdout, stderr = Open3.popen3(bash_cmd)
begin
begin
puts 'out -> ' + stdout.read_nonblock(maxlen)
end while true
rescue IO::WaitReadable
IO.select([stdout])
retry
rescue EOFError
puts 'EOF'
end
end
Run Code Online (Sandbox Code Playgroud)
我假设您将require 'open3'在测试任一功能之前.
为什么IO::WaitReadableSTDOUT的提升方式与STDERR不同?
如果您拥有它们,使用其他方法启动子进程的变通方法也很受欢迎.
在大多数操作系统中,STDOUT 被缓冲,而 STDERR 则没有。其popen3作用基本上是在您启动的可执行文件和 Ruby 之间打开一个管道。
任何处于缓冲模式的输出都不会通过此管道发送,直到出现以下情况:
STDERR 不缓冲的原因是,通常认为错误消息立即出现很重要,而不是通过缓冲来提高效率。
因此,了解了这一点,您可以使用 STDOUT 来模拟 STDERR 行为,如下所示:
#!/usr/bin/env ruby
3.times do
STDOUT.puts 'message on stdout'
STDOUT.flush
STDERR.puts 'message on stderr'
sleep 1
end
Run Code Online (Sandbox Code Playgroud)
你会看到差异。
您可能还想检查“了解 Ruby 和操作系统 I/O 缓冲”。