STDOUT&tee /dev/null>(wc -l> tmp.txt)のトリプルパイピングと `cat tmp.txt`を含めるための再パイピングの奇妙な結果

STDOUT&tee /dev/null>(wc -l> tmp.txt)のトリプルパイピングと `cat tmp.txt`を含めるための再パイピングの奇妙な結果
$ seq 1 12773 | tee /dev/null >(wc -l > tmp.txt) | head -$((0x`openssl rand -hex 7` % `cat tmp.txt` + 1))|tail -1

--> 8473(任意で1〜12773の間)

$ cat tmp.txt

--> 8473

$ seq 1 12774 | tee /dev/null >(wc -l > tmp.txt) | head -$((0x`openssl rand -hex 7` % `cat tmp.txt` + 1))|tail -1

-->(空)

$ cat tmp.txt

--> 8844(任意で1〜12773の間)

$ seq 1 25011 | tee /dev/null >(wc -l > tmp.txt) | cat | head -$((0x`openssl rand -hex 7` % `cat tmp.txt` + 1))|tail -1

--> 13778(任意で1〜25011の間)

$ cat tmp.txt

--> 13778

$ seq 1 25012 | tee /dev/null >(wc -l > tmp.txt) | cat |head -$((0x`openssl rand -hex 7` % `cat tmp.txt` + 1))|tail -1

-->(空)

$ cat tmp.txt

--> 24939(1〜25012の間で任意に)

$ seq 1 46014 | tee /dev/null >(wc -l > tmp.txt) | cat | cat |head -$((0x`openssl rand -hex 7` % `cat tmp.txt` + 1))|tail -1

--> 34111(任意で1〜46014の間)

$ cat tmp.txt

--> 34111(任意で1〜46014の間)

$ seq 1 46015 | tee /dev/null >(wc -l > tmp.txt) | cat | cat |head -$((0x`openssl rand -hex 7` % `cat tmp.txt` + 1))|tail -1

-->(空)

$ cat tmp.txt

--> 343(任意で1〜46014の間)

cat の後の '|'(wc -l > tmp.txt)' 個数が増えるほど、上記コマンドが処理する行数を増やすことができます。

どうなりますか?

ベストアンサー1

〜のようにアレックスPすでにコメントで説明していますが、パイプラインのコマンドは並列に実行されます。。あなたはこれが真実ではないと確信しているようです。心を開かない限り、何が起こっているのか理解できないという誤解を忘れてください。

プロセスは並列に実行されるため、ジョブの順序は正確な時間に依存し、ある実行から次の実行に複製されない可能性があります。

最初の例では、次のコマンドが並列に実行されます。

  • seq 1 12773
  • tee /dev/null
  • wc -l > tmp.txt(プロセス交換もパイプを生成し、コマンドを並列に実行します)
  • head -$((0x`openssl rand -hex 7` % `cat tmp.txt` + 1))- これには3つの異なるコマンドが含まれ、両方のコマンドがhead終了opensslしたcat後に開始されます。
  • tail -1

並列に実行されるため、wc -l > tmp.txt次の出力に関連するランタイムは予測できません。cat tmp.txtcat tmp.txtwc

  • リダイレクトを実行する前に実行することができtmp.txt、以前の実行からファイルをインポートするか(存在する場合)、ファイルが存在しないと文句を言うことができます。
  • リダイレクトの実行後に実行できますが、wcこの場合、リダイレクトによってファイルが切り捨てられるため、出力が生成される前にファイルは空です。
  • 出力の生成中に実行できwc、出力の先頭のみを選択します。ほとんどのシステムでは、wc出力が自動的に生成されるため(短いため)、これは発生しません。
  • wc出力完了後に実行できます。

実験を通して私はあなたと同じ結果を得ました(ほとんどアイドル状態のカーネル3.16を実行しているLinuxシステムで)。 、の出力をseq 1 12773取得するには。 、を使って空のファイルを選択してください。それでは、12773と12774の間に違いがあるのはなぜですか?しかし、その下の結果はかなり信頼できますか?cat tmp.txtwcseq 1 12774cat tmp.txt

$ seq 1 12774 | wc -c
65538

しきい値は65536バイトで、値は次のとおりです。パイプバッファ容量。このコマンドは最初に実行して完了するhead …必要があるため、起動速度が遅くなります。開始すると、パイプの前のコマンドがパイプバッファに書き込まれます。パイプバッファがいっぱいになったら、前のコマンドを停止する必要があります。数値が 12773 に達した場合、パイプバッファーは決して埋められないため、実行が以前に完了し (必要な作業がはるかに少なかった)、出力を作成する時間があった可能性が高くなります。ただし、数値が12774を超えると、パイプバッファがいっぱいになり、出力書き込みが中断され、まだ出力書き込みが完了していません。また、空のファイルとして実行します。opensslcatseqopensslwcteehead …wccat

teeより多くのパイプを追加すると、各パイプには独自のバッファがあるため、遅延する前により多くのスペースがあります。

おすすめ記事