重定向时,为什么Ruby的STDERR输出比前面的STDOUT输出来得早?
在bash中,这将按预期顺序提供输出:重定向时,为什么Ruby的STDERR输出比前面的STDOUT输出来得早?,ruby,bash,Ruby,Bash,在bash中,这将按预期顺序提供输出: ruby -e "puts 'one'; raise 'two'" one -e:1:in `<main>': two (RuntimeError) ruby-e“放‘一’;放‘二’” 一 -e:1:in`:2(运行时错误) 但是,如果我将STDERR重定向到STDOUT,我会在输出之前得到错误,这是我不想要的: ruby -e "puts 'one'; raise 'two'" 2>&1 | cat -e:1:in `<
ruby -e "puts 'one'; raise 'two'"
one
-e:1:in `<main>': two (RuntimeError)
ruby-e“放‘一’;放‘二’”
一
-e:1:in`:2(运行时错误)
但是,如果我将STDERR重定向到STDOUT,我会在输出之前得到错误,这是我不想要的:
ruby -e "puts 'one'; raise 'two'" 2>&1 | cat
-e:1:in `<main>': two (RuntimeError)
one
ruby-e“放‘一’;升起‘二’”2>&1“猫”
-e:1:in`:2(运行时错误)
一
我想将输出重定向到文本文件(其行为方式与上面的
cat
相同),并获取输出和异常,但顺序与在我的终端中查看输出时相同。这可以实现吗?这是因为标准输出并不总是立即输出,要强制它输出,您可以使用IO\flush
:
puts "one"
$>.flush
另一方面,STDERR总是立即输出。根据毛里西奥和吉尔喜欢玉米饼的回答,我(通过)得出了以下结论: 或者,如果可以修改脚本本身,请将该行添加到开头
谢谢大家! 发生这种情况的原因是行缓冲与块缓冲。您可以控制缓冲的类型,可以在希望其输出同步的点刷新缓冲,也可以等到退出时刷新所有内容。除非以某种方式强制执行,否则缓冲取决于输出是否为tty-type1文件描述符,因此重定向到管道会改变模式 具体而言:
true false
------------- --------------
$stdout.tty? line-buffered block-buffered
$stderr.tty? line-buffered line-buffered
您可以使用以下相同方式配置它们:
$stdout.sync = $stderr.sync = true # or false, of course
我的测试用例:
$stdout.sync = $stderr.sync = true
$stdout.puts 'stdout a'
sleep 2
$stdout.puts 'stdout b'
sleep 2
$stderr.puts 'stderr a'
sleep 2
$stderr.puts 'stderr b'
sleep 2
1.参见ttyname(3)。
应该这样做STDEER总是打印到流中,而STDOUT通常被缓冲以进行打印。这就是我最终使用它的原因:
IO#如果需要多次刷新缓冲区,则刷新
是一个更好的选择flush
是单次刷新,sync
将手柄放下,您必须晃动手柄才能使其停止运行。:-)还是很有帮助的答案。
$stdout.sync = $stderr.sync = true # or false, of course
$stdout.sync = $stderr.sync = true
$stdout.puts 'stdout a'
sleep 2
$stdout.puts 'stdout b'
sleep 2
$stderr.puts 'stderr a'
sleep 2
$stderr.puts 'stderr b'
sleep 2