考虑以下命令:
bash -c "echo x; cat 1" | tee 1
.
我的理解是,它将分叉到一个新的 shell,写入x
stdout,写入file 1 not found
stderr,退出并将控制权返回给父进程,然后写入x
stdout 和 to 1
。因此,我期望最终输出为x
,并且该文件1
恰好包含字符串x
。
然而,这种情况并非如此。实际上,该文件1
通常包含至少两个 s 实例x
,有时甚至包含数千行x
s。在运行该命令一万次的批量测试中,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
。两者肯定是交替的,所以是的,正如怀疑的那样,这都是关于两个命令的执行时间(我想是上下文切换)。