鉴于以下红宝石:
$i = 0
$num = 3
while $i < $num do
puts "My loop just executed"
sleep 10
$i +=1
end
Run Code Online (Sandbox Code Playgroud)
我希望每10秒(加上执行时间)我会将"我的循环刚执行"打印到我的控制台,直到$ i = 3
My loop just executed
# sleeps for 10 seconds
My loop just executed
# sleeps for 10 seconds
My loop just executed
# sleeps for 10 seconds
Run Code Online (Sandbox Code Playgroud)
然而,实际发生的是脚本运行,在$ i = 3之前没有任何内容打印到控制台,然后我立刻打印3行:
My loop just executed
My loop just executed
My loop just executed
Run Code Online (Sandbox Code Playgroud)
我不明白为什么它不会在每个循环后打印而不是打印到最后?
为什么这样,我怎么能让它像我期待的那样工作呢?任何帮助,将不胜感激
控制台输出是缓冲的,没人答应给IO#flush你:
$i = 0
$num = 3
while $i < $num do
$stdout.puts "My loop just executed"
$stdout.flush
sleep 10
$i +=1
end
Run Code Online (Sandbox Code Playgroud)
如果stdout是终端设备(tty),Ruby会自动刷新输出,如果不是,则缓冲输出.
例如,从终端运行此命令通常会立即输出"hello":
$ ruby -e 'puts "hello" ; sleep 5 ; puts "world"'
hello
# 5 seconds delay
world
$
Run Code Online (Sandbox Code Playgroud)
因为:
$ ruby -e 'puts $stdout.tty?'
true
Run Code Online (Sandbox Code Playgroud)
而输出到另一个命令通常会延迟(即缓冲)输出,直到脚本完成为止:
$ ruby -e 'puts "hello" ; sleep 5 ; puts "world"' | cat
# 5 seconds delay
hello
world
$
Run Code Online (Sandbox Code Playgroud)
因为:
$ ruby -e 'puts $stdout.tty?' | cat
false
Run Code Online (Sandbox Code Playgroud)
要立即刷新任何输出,无论标准输出是一个TTY,您可以设置$stdoutS" sync到true你的脚本的开头:
$stdout.sync = true
Run Code Online (Sandbox Code Playgroud)
适用于上面的例子:
$ ruby -e '$stdout.sync = true ; puts "hello" ; sleep 5 ; puts "world"' | cat
hello
# 5 seconds delay
world
$
Run Code Online (Sandbox Code Playgroud)