web-dev-qa-db-ja.com

Tにパイピングするときの標準出力の強制ラインバッファリング

通常、stdoutは行バッファリングされます。言い換えれば、printf引数が改行で終わる限り、その行が即座に印刷されると期待できます。パイプを使用してteeにリダイレクトする場合、これは保持されないようです。

私はC++プログラムaを持っています。これは、常に_\n_-で終わる文字列をstdoutに出力します。

単独で実行すると(_./a_)、期待どおりにすべてが正しく適切なタイミングで印刷されます。ただし、tee(_./a | tee output.txt_)にパイプすると、終了するまで何も出力されず、teeを使用する目的に反します。

C++プログラムの各印刷操作の後にfflush(stdout)を追加することで修正できることを知っています。しかし、よりクリーンで簡単な方法はありますか?たとえば、パイプを使用している場合でも、stdoutを強制的に行バッファリングするコマンドを実行できますか?

100
houbysoft

unbuffer パッケージの一部である expect を試してください。すでにシステム上にあるかもしれません。

あなたの場合、次のように使用します:

./a | unbuffer -p tee output.txt

-pは、unbufferがstdinから読み取り、それを残りの引数でコマンドに渡すパイプラインモード用です。

50

あなたは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.

stdbufteeを実行していないので、aで実行しているので、aのソースでaのストリームのバッファリングを設定しない限り、これは影響しません。

また、stdbufnot POSIXですが、GNU-coreutilsの一部です。

113
c00kiemon5ter

scriptコマンドを使用して、擬似端末でコマンドを実行しようとすることもできます(パイプへのラインバッファー出力を強制する必要があります)。

script -q /dev/null ./a | tee output.txt     # Mac OS X, FreeBSD
script -c "./a" /dev/null | tee output.txt   # Linux

scriptコマンドは、ラップされたコマンドの終了ステータスを伝播しないことに注意してください。

26
jon

Stdio.hからsetlinebufを使用できます。

setlinebuf(stdout);

これにより、バッファリングが「ラインバッファリング」に変更されます。

さらに柔軟性が必要な場合は、setvbufを使用できます。

18

代わりにC++ストリームクラスを使用する場合、すべての_std::endl_ isは暗黙的なフラッシュです。 Cスタイルの印刷を使用して、あなたが提案した方法(fflush())が唯一の方法だと思います。

2
Kevin Grant