「tee」、fifos、および「paste」を使用してデータフローを分岐するとき、どのような問題がありますか?

「tee」、fifos、および「paste」を使用してデータフローを分岐するとき、どのような問題がありますか?

精神的にこの問題、単一のソースから分岐したデータストリームを作成したいと思います。

cmd1 ──> tee ──────────────> │          
         ├─────> cmd2 ─────> │ cmd4  
         └─────> cmd3 ─────> │

この質問とは異なり、一度に1つのコマンドではなく出力をインターリーブしたいと思います。名前付きパイプを使用してこれを行うことができますpaste

$ mkfifo fifo1 fifo2
$ seq 1 100 \
    | tee \
      >(awk '$0+=1' > fifo1) \
      >(awk '$0+=2' > fifo2) \
    | paste - fifo1 fifo2

これはうまくいくようです。つまり、印刷されます。

1 2 3
2 3 4
...
100 101 102

以下は、概念を説明する概念的な例です。私のもの本物パイプラインは次のとおりです。

find "$1" -type d -print0 \
  | tee \
    >(xargs -0 -n1 du -bs | cut -f1 > fifo1) \
    >(xargs -0 -n1000 stat --printf="%G\n" > fifo2) \
  | xargs -0 -n1 echo \
  | paste - fifo1 fifo2

これはまた、ほとんどの場合、かなりうまく機能するようです。しかし、巨大なファイルシステムで実行すると、途中で停止します。上記の質問を読んでみると、デッドロックに陥ったようです。しかし、それがどこにあるのかはわかりません。pasteすべてのデータフローを維持する必要があるようです。

tee私はまだバッファリングとストリーミング、パイプとFIFOを理解していないようです。私がここで何を見逃しているのかを説明できる人はいますか?詰まった部分はどこにあり、どのように修正しますか? (それとももっと調べてみますか?)

ベストアンサー1

並列書き込みおよび読み取りパイプラインには厳密な規律が必要です。

パイプが128KBytesをバッファリングできると仮定します。今、すべてのファイル名の長さが1MBであるとします。ファイル名がパイプに合わないため、リーダーは残りを書き込む前にファイル名の一部を読み取る必要があります。ただし、リーダーが現在別のパイプの入力を待っている場合、これは発生しません。

あなたの例では、xargs -n1000出力される前に1000MBytesを読み取るので、stdoutに書き込もうとしている間に入力をpaste待ちます。$fifo2tee

この試み:

du_cut() { du -bs "$1" | cut -f1; }
stat_print() { stat --printf="%G\n" "$1"; }
doit() { printf "%s\t%s\n" $(du_cut "$1") $(stat_print "$1"); }
export -f du_cut stat_print doit
find "$1" -type d -print0 | parallel -0 --tag doit

おすすめ記事