通常、stdout
は行バッファリングされます。言い換えれば、printf
引数が改行で終わる限り、その行が即座に印刷されると期待できます。パイプを使用してtee
にリダイレクトする場合、これは保持されないようです。
私はC++プログラムa
を持っています。これは、常に_\n
_-で終わる文字列をstdout
に出力します。
単独で実行すると(_./a
_)、期待どおりにすべてが正しく適切なタイミングで印刷されます。ただし、tee
(_./a | tee output.txt
_)にパイプすると、終了するまで何も出力されず、tee
を使用する目的に反します。
C++プログラムの各印刷操作の後にfflush(stdout)
を追加することで修正できることを知っています。しかし、よりクリーンで簡単な方法はありますか?たとえば、パイプを使用している場合でも、stdout
を強制的に行バッファリングするコマンドを実行できますか?
あなたはstdbuf
を試すことができます
$ stdbuf -o 0 ./a | tee output.txt
(大きな)manページの一部:
-i, --input=MODE adjust standard input stream buffering
-o, --output=MODE adjust standard output stream buffering
-e, --error=MODE adjust standard error stream buffering
If MODE is 'L' the corresponding stream will be line buffered.
This option is invalid with standard input.
If MODE is '0' the corresponding stream will be unbuffered.
Otherwise MODE is a number which may be followed by one of the following:
KB 1000, K 1024, MB 1000*1000, M 1024*1024, and so on for G, T, P, E, Z, Y.
In this case the corresponding stream will be fully buffered with the buffer
size set to MODE bytes.
ただし、これに留意してください。
NOTE: If COMMAND adjusts the buffering of its standard streams ('tee' does
for e.g.) then that will override corresponding settings changed by 'stdbuf'.
Also some filters (like 'dd' and 'cat' etc.) dont use streams for I/O,
and are thus unaffected by 'stdbuf' settings.
stdbuf
でtee
を実行していないので、a
で実行しているので、a
のソースでa
のストリームのバッファリングを設定しない限り、これは影響しません。
また、stdbuf
はnot POSIXですが、GNU-coreutilsの一部です。
script
コマンドを使用して、擬似端末でコマンドを実行しようとすることもできます(パイプへのラインバッファー出力を強制する必要があります)。
script -q /dev/null ./a | tee output.txt # Mac OS X, FreeBSD
script -c "./a" /dev/null | tee output.txt # Linux
script
コマンドは、ラップされたコマンドの終了ステータスを伝播しないことに注意してください。
Stdio.hからsetlinebufを使用できます。
setlinebuf(stdout);
これにより、バッファリングが「ラインバッファリング」に変更されます。
さらに柔軟性が必要な場合は、setvbufを使用できます。
代わりにC++ストリームクラスを使用する場合、すべての_std::endl
_ isは暗黙的なフラッシュです。 Cスタイルの印刷を使用して、あなたが提案した方法(fflush()
)が唯一の方法だと思います。