我很难理解以下命令的效果:
yes | tee hello | head
在我的笔记本电脑上,“hello”中的行数约为 36000 行,远高于标准输出上显示的 10 行。
我的问题是:
yes
,以及更一般地说,管道中的命令何时停止?为什么上面两个数字不匹配。是因为
tee
没有将行一一传递到管道中的下一个命令吗?
答案1
:> yes | strace tee output | head
[...]
read(0, "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 8192) = 8192
write(1, "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 8192) = 8192
write(3, "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 8192) = 8192
read(0, "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 8192) = 8192
write(1, "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 8192) = -1 EPIPE (Broken pipe)
--- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=5202, si_uid=1000} ---
+++ killed by SIGPIPE +++
从man 2 write
:
EPIPE
fd 连接到读取端封闭的管道或插座。当发生这种情况时,写入进程还将收到 SIGPIPE 信号。
所以进程从右到左死亡。head
自行退出,退出tee
后第一次尝试写入管道时被杀死。死后head
也会发生同样的情况。yes
tee
tee
可以写入管道,直到缓冲区已满。但它可以向文件写入任意内容。看来我的版本tee
将相同的块写入stdout
文件。
head
它的(即内核的)读缓冲区有8K。它会读取所有内容,但仅打印前 10 行,因为这是它的工作。
答案2
写入管道的程序将收到信号管道当管道读取器终止时发出信号,并且只要其标准输入保持打开状态,tee(1)就不会终止。
head(1)默认输出10行。