在bash中,这以预期的顺序给出输出:
ruby -e "puts 'one'; raise 'two'"
one
-e:1:in `<main>': two (RuntimeError)
Run Code Online (Sandbox Code Playgroud)
但是如果我将STDERR重定向到STDOUT,我会在输出之前得到错误,这是我不想要的:
ruby -e "puts 'one'; raise 'two'" 2>&1 | cat
-e:1:in `<main>': two (RuntimeError)
one
Run Code Online (Sandbox Code Playgroud)
我想将输出重定向到文本文件(它的行为与cat
上面相同)并获得输出和异常,但顺序与查看终端输出时的顺序相同.这可以实现吗?
这是因为行缓冲与块缓冲.您可以控制缓冲的类型,您可以在希望其输出同步的位置刷新它们,或者您可以等到退出,此时所有内容都会被刷新.除非你以某种方式强制它,否则缓冲取决于输出是否是tty-type 1文件描述符,因此重定向到管道会改变模式.
特别:
true false
------------- --------------
$stdout.tty? line-buffered block-buffered
$stderr.tty? line-buffered line-buffered
Run Code Online (Sandbox Code Playgroud)
您可以使用相同的方式配置它们:
$stdout.sync = $stderr.sync = true # or false, of course
Run Code Online (Sandbox Code Playgroud)
我的测试用例:
$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
Run Code Online (Sandbox Code Playgroud)
这是因为 STDOUT 并不总是立即输出,要强制它输出,您可以使用IO#flush
:
puts "one"
$>.flush
Run Code Online (Sandbox Code Playgroud)
另一方面,STDERR 总是立即输出。