ティーアンドペーストを使用すると、デッドロックが発生する可能性があります。

ティーアンドペーストを使用すると、デッドロックが発生する可能性があります。

別の処理のために、teeを使用してコマンドの標準出力を2つの「分岐」にリダイレクトしようとしています。最後に、貼り付けを使用して2つの「分岐」の結果をマージする必要があります。私は生産者のために次のコードを思いつきました。

mkfifo a.fifo b.fifo
python -c 'print(("0\t"+"1"*100+"\n")*10000)' > sample.txt
cat sample.txt | tee >(cut -f 1 > a.fifo) >(cut -f 2 > b.fifo) | awk '{printf "\r%lu", NR}'
# outputs ~200 lines instantly
# and then ~200 more once I read from pipes

その後、別の端末で消費者を起動します。

paste a.fifo b.fifo | awk '{printf "\r%lu", NR}'
# outputs ~200 once producer is stopped with ctrl-C

問題はそれが停止することです。この動作は入力の長さによって異なります。

  1. 入力行が小さい場合(つまり、2番目の列に100文字ではなく30文字が含まれている場合)、これはうまく機能します。
  2. 同じ(または同様の長さ)入力が入力a.fifoとして与えられると、うまく動作するようです。b.fifo

a.fifo問題はsayから短いチャンクを供給しb.fifo。この動作はパイプを指定する順序には依存しませんpaste

私はLinuxとそのパイプロジックについてはよくわかりませんが、何とか詰まっているようです。私の質問は、これが何とか安定して達成できるかどうかです。それでは、どうすればいいですか?おそらくteeandを使用せずに他の方法がありますかpaste

答え1

問題を詳しく理解できませんでした。明らかに、これはいくつかのバッファを満たす各ラインのサイズの違いに関連しています。

この問題は、バッファを拡大することで「解決」することができます。

paste a.fifo <(buffer <b.fifo) | awk '{printf "\r%lu", NR}'

面白い事実:bufferビルドコマンドにaを追加するとawk完了できますが、コマンドを使用するとまだブロックされます(私の場合はほぼ終わり)。

$ cat sample.txt | tee >(cut -f 1 > a.fifo) >(cut -f 2 | buffer > b.fifo) | awk '{printf "\r%lu", NR}; END { print; print NR; }'
10001


$ paste a.fifo b.fifo | awk '{printf "\r%lu", NR}'
8152

IMHO、言うことはできません。バグが関係していても驚かないでしょう。

関連情報