次のコマンドを検討してください
bash -c "echo x; cat 1" | tee 1
。
私の理解は新しいシェルにフォークし、x
stdoutに書き込み、file 1 not found
stderrに書き込み、終了し、親プロセスに制御を返し、x
stdoutと1
.したがって、最終出力はでありx
、ファイルには1
正確に文字列が含まれると予想されますx
。
しかし、これは事実ではありません。実際、ファイルには1
通常少なくとも 2 つの s インスタンスが含まれ、x
時には数千行のx
s が含まれます。このコマンドを1万回実行したバッチテストで、x
ファイルに記録されたsの平均数は52.3個、中央値は1個でした。どのようなメカニズムによってこのようなことが起こりますか?この行動の確率分布は何ですか?私はそれが条件的に幾何学的であり、他の点では均一であると思います。
答え1
これは非常に奇妙な問題なので、straceの助けを借りて調査してみました。コマンドを1000回繰り返します。
mkdir {000..999}
for i in {000..999}; do
echo $i
(cd $i; strace -f -o trace.log bash -c 'bash -c "echo x; cat 1" | tee 1 >/dev/null'; )
done
wc -l */1 | sort -nr | head -n2
最も多くの行()があるファイルを見つけてそれに応じて確認すると、trace.log
次のような内容がたくさん表示されます。
7567 <... read resumed> "x\n", 8192) = 2
7567 write(1, "x\n", 2) = 2
7567 write(3, "x\n", 2) = 2
7567 read(0, <unfinished ...>
7568 read(3, "x\n", 131072) = 2
7568 write(1, "x\n", 2) = 2
7567 <... read resumed> "x\n", 8192) = 2
7567 write(1, "x\n", 2) = 2
7567 write(3, "x\n", 2) = 2
7567 read(0, <unfinished ...>
7568 read(3, "x\n", 131072) = 2
7568 write(1, "x\n", 2) = 2
7567 <... read resumed> "x\n", 8192) = 2
7567 write(1, "x\n", 2) = 2
7567 write(3, "x\n", 2) = 2
7567 read(0, <unfinished ...>
ここで、7567はで、tee 1
7568はですcat 1
。 2つは間違いなく交互になるので、疑いがあるように2つのコマンドの実行時間に関するものです(コンテキスト切り替えだと思います)。