シェル標準出力を2つのコマンドに変換し、プログラムが中断されました

シェル標準出力を2つのコマンドに変換し、プログラムが中断されました

配列パーセンタイルを計算するサンプルシェルコマンドがあります。

$ time zcat input.txt.gz | head -n 999999 | awk 'BEGIN{FS="\t"}{print $13}' | st
--percentile=97.5
75

real    0m3.532s
user    0m8.584s
sys     0m0.648s

2つのパーセンタイルで数字を計算したいので、速度が速いことがわかります。 teeを使用してstdoutをコマンドにリダイレクトします。

mkfifo output_txt;
zcat input.txt.gz | head -n 999999 |
   awk 'BEGIN{FS="\t"}{print $13}' |
   tee >(st --percentile=2.5) >> output_txt |
   st --percentile=97.5 >> output_txt;
cat output_txt; rm output_txt

しかし、それは外に出て立ち往生していません。

fifoを使うべきだと思うので、次のように変更しました。

echo "" > output_txt;
zcat input.txt.gz | head -n 999999 |
   awk 'BEGIN{FS="\t"}{print $13}' |
   tee >(st --percentile=2.5) >> output_txt |
   st --percentile=97.5 >> output_txt;
cat output_txt; rm output_txt

実行されますが、長い数字のリストを出力し、プログラムが各行の分位数を計算するようです。

input.txt生成できる

for ((i=0; i<999999; i++)); do
  number=$(awk 'BEGIN{print int(rand()*1000)/10}')
  echo $number >> input.txt
done

=====更新======

@ilkkachuが述べたように、次のコマンドはうまくいきます。

echo "" > output_txt;
zcat input.txt | head -n 999999 |
   awk 'BEGIN{FS="\t"}{print $13}' |
   tee >(st --percentile=2.5 >> output_txt) |
   st --percentile=97.5 >> output_txt;
cat output_txt; rm output_txt

しかし、fifoを使うときは動作しません(まだ付いています)。

アップデート:@Paul_Pedant

FIFOはパイプです。インポートするデータが一部のシステム制限(おそらく4096バイト(POSIX最小)または64KB(通常のLinux)またはその他の制限)に達すると、fifoは他のプロセスが一部のデータを読み取るまで書き込みをブロックします。

これがfifoを使うときに詰まる理由を説明すると思います。

関連情報