1

私は coprocを使用しようとしていますが、おそらくバッファリングで問題が発生しています。標準入力からの行指向の入力を受け入れ、入力行ごとに標準出力に行を出力する複雑なコマンドがあります。コマンドラインでは、このコマンドは行ごとに正常に機能しますが、コプロシージャに入れて${COPROC[0]}FD から読み取ると、読み取りがブロックされます。

この動作は で再現できますが、 では再現できpasteませんcat。パラメータが渡されなかった場合、私はほとんど同じことを期待pasteしています。catこれは、コマンド プロンプトで直接実行する場合です。

$ cat
Hello World!<RETURN>
Hello World!^D
$ paste
Hello World!<RETURN>
Hello World!^D
$ 

(説明のためRETURN^D追加)

しかし、これらをに入れると、動作が異なります-cat厳密に行バッファリングされpasteていますが、はるかに大きなバッファで動作しているようです:

$ coproc cat
$ echo 'Hello world!' >&${COPROC[1]}
$ read -ru ${COPROC[0]} line; echo $line
Hello world!
$ kill $COPROC_PID
[3]+  Terminated              coproc COPROC cat
$ 
$ coproc paste
[3] 42657
$ echo 'Hello world!' >&${COPROC[1]}
$ read -ru ${COPROC[0]} line; echo $line
#### read blocks here until ^C ####

pasteこの理由は、接続先に応じてバッファリングモードを調整するためだと思いますが、cat常にラインバッファリングモードになっています。

coproc で強制的にpaste(または他の一般的なコマンドを) ライン バッファリングする方法はありますか?


もう少し実験を重ねた結果、 catを使用せずに と の間をパイプするだけで、同様の動作を再現できることがわかりましたpaste

$ cat | cat
Hello World!<RETURN>
Hello World!^D
$ cat | paste
Hello World!<RETURN>
Hello World!^D
$ paste | cat
Hello World!<RETURN>
#### command blocks here until ^C ####

(説明のためRETURN^D追加)

  • 最初に、パイプcatcatて行バッファリングを取得しますが、
  • 次に、パイプcatしてpaste行バッファリングを取得します
  • 最後に、パイプpasteしてcat行バッファリングを取得しません

これは、 がインタラクティブ モードの場合は stdout をライン バッファリングすることを示しているように見えpasteますが、それ以外の場合は、はるかに大きなバッファを使用します。

4

1 に答える 1

0

ライン バッファリングを強制する 1 つの方法は、stdbuf利用可能な場合は coreutils ツールを使用することです。

stdbufプログラムに関連付けられた 3 つの標準 I/O ストリームのバッファリング操作を変更できます

このcoproc場合:

$ coproc stdbuf -oL paste
[3] 42751
$ echo 'Hello world!' >&${COPROC[1]}
$ read -ru ${COPROC[0]} line; echo $line
Hello world!
$ kill $COPROC_PID
[3]+  Terminated              coproc COPROC stdbuf -oL paste
$ 

pastetoケースの単純なパイプのcat場合:

$ stdbuf -oL paste | cat
Hello World!<RETURN>
Hello World!^D
$ 
于 2014-01-07T18:58:12.587 に答える