2012-01-17 14 views
6

が、これは予想される順序で出力が得られます。リダイレクト時にSTDOUT出力が以前のSTDOUT出力より前に来るのはなぜですか? bashで

ruby -e "puts 'one'; raise 'two'" 
one 
-e:1:in `<main>': two (RuntimeError) 

しかし、私はSTDOUTにSTDERRをリダイレクトする場合、私はしたくない出力、前にエラーが発生します。

ruby -e "puts 'one'; raise 'two'" 2>&1 | cat 
-e:1:in `<main>': two (RuntimeError) 
one 

私は出力をテキストファイルにリダイレクトしたい(それは上記と同じように動作する)。出力と例外の両方を取得するが、端末の出力を見るのと同じ順序で行う。これは達成できますか?

+1

STDEERは常にストリームに印刷されて行う必要があります。 –

答えて

2

それはSTDOUTがすぐにいつもの出力をしないため、出力にそれを強制することです、あなたはIO#flushを使用します。

puts "one" 
$>.flush 

STDERR一方、常に即座に出力します。マウリシオさんとGIRは、タコスの回答を愛するに基づいて

+0

バッファを2回以上フラッシュする必要がある場合は、 'IO#flush'が良い選択です。 'flush'はシングルフラッシュで、' sync'はハンドルダウンしてしまい、実行を止めるためにはそれを揺らす必要があります。 :-) –

0

、私は(How to turn on STDOUT.sync in ruby from the command line経由)この思い付いた:

ruby -r "/tmp/sync.rb" -e "puts 'one'; raise 'two'" 2>&1 | cat 
one 
-e:1:in `<main>': two (RuntimeError) 

/tmp/sync.rb

STDOUT.sync=true 

それとも、スクリプト自体を変更することができる場合が含まれ、その行を先頭に追加します。

ありがとうございました!

+0

これは私がそれを使用して終わったものです:https://github.com/henrik/vim-ruby-runner/commit/d4b8cee927a265bbd016a42cf98f570eb33512ad –

9

これは、ラインバッファリングとブロックバッファリングのために発生します。バッファリングのタイプを制御することができます。出力を同期させたいポイントでそれらをフラッシュすることができます。あるいは、すべてがフラッシュされた時点で終了するまで待つことができます。一方向または他方向に強制しない限り、バッファリングは、出力がttyタイプのファイル記述子であるであるかどうかによって決まります。したがって、パイプへのリダイレクションによってモードが変更されます。具体的に

$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

    true   false 
       ------------- -------------- 
$stdout.tty? line-buffered block-buffered 
$stderr.tty? line-buffered line-buffered 

あなたは、両方のと同じ方法でそれらを設定することができます)。

+1

まだ役に立ちました。 – sashaegorov

0

ruby -e STDOUT.sync=true -e "puts 'one'; raise 'two'" 2>&1 | cat

はSTDOUTは通常印刷するバッファリングされている間、それは

関連する問題