パイプで標準出力バッファリングをオフにする方法は?

パイプで標準出力バッファリングをオフにする方法は?

2つのコマンドを呼び出すスクリプトがあります。

long_running_command | print_progress

印刷にlong_running_command進展がありましたが、満足できませんでした。私はそれをより良くしようとしましたprint_progress(つまり、進行状況を1行に印刷します)。

質問:stdoutにパイプを接続すると4Kバッファもアクティブになるので、きれいな印刷プログラムは何も得られません...何も...何も...たくさん...:)

4Kバッファを無効にするにはどうすればよいですかlong_running_command? (いいえ、ソースコードはありません。)

答え1

この猫の皮をむくもう一つの方法は次のとおりです。stdbufGNU Coreutilsの一部であるプログラムです(FreeBSDにも独自のプログラムがあります)。

stdbuf -i0 -o0 -e0 command

これにより、入力、出力、およびエラーバッファリングが完全にオフになります。一部のアプリケーションでは、パフォーマンス上の理由から、行バッファリングがより適している可能性があります。

stdbuf -oL -eL command

これは、動的にリンクされたアプリケーションのバッファstdioリング(printf()fputs()...)でのみ機能し、そのアプリケーション自体が標準ストリームのバッファリングを調整しない場合にのみ機能します。ただし、これはほとんどのアプリケーションに適用する必要があります。

答え2

あなたはそれを使用することができますunbufferコマンド(次のようにexpectパッケージ)、例えば

unbuffer long_running_command | print_progress

unbuffer疑似端末(pty)を介して接続すると、long_running_commandシステムはそれを対話型プロセスとして扱うため、パイプで4kiBバッファを使用しないため、待ち時間が発生する可能性があります。

長いパイプの場合は、すべてのコマンド(最後のコマンドを除く)をバッファリング解除する必要があるかもしれません。

unbuffer x | unbuffer -p y | z

答え3

の場合、grep出力をラインバッファリングするように強制できますsedawkあなたはそれを使用することができます:

grep --line-buffered

出力をラインバッファリングするよう強制します。デフォルトでは、出力は標準出力が端末の場合はラインバッファリングされ、そうでない場合はブロックバッファリングされます。

sed -u

出力ラインをバッファリングします。

詳しくはこのページをご覧ください。 http://www.perkin.org.uk/posts/how-to-fix-stdio-buffering.html

答え4

出力が端末に到達しないときにlibcがバッファリング/フラッシングを修正するのに問題がある場合は、次のことを試してください。ソカット。ほぼすべてのタイプのI / Oメカニズム間で双方向ストリームを生成できます。その一つは、擬似ttyと通信するフォークプログラムです。

 socat EXEC:long_running_command,pty,ctty STDIO 

その機能は

  • 擬似tty生成
  • long_running_commandをフォークし、ptyのスレーブ側をstdin / stdoutに設定します。
  • ptyの基本側面と2番目のアドレス(ここではSTDIO)の間に双方向ストリームを設定します。

これが同じ出力を提供するならば、long_running_commandパイプを使い続けることができます。

編集:うわー、バッファリングされていない答えを見ませんでした!まあ、とにかくsocatは素晴らしいツールなので、おそらくこの答えを残すでしょう。

関連情報