我有这个:
$ ls -lh file
-rw-r--r-- 1 ankur root 181M Sep 23 20:09 file
$ head -6 file
z
abc
abc
abc
abc
abc
$ cat file | grep -m 1 z
z
问题:
为什么最后一行中的cat
命令行没有过早地使用SIGPIPE死亡?我认为这应该发生,因为grep
与猫{183}文件的cat file
相比没有时间终止。随着读取过程消失cat
将尝试写入损坏的管道并且应该使用SIGPIPE消亡。
更新
我最后写了这篇文章:readstdin.c
# include <unistd.h>
# include <stdio.h>
int main() {
ssize_t n ;
char a[5];
n = read(0, a, 3);
printf("read %zd bytes\n", n);
return(0);
}
我这样用:
$ cat file | ./readstdin
$ yes | ./readstdin
但仍然cat
或yes
不会过早死亡。我期待它,因为通过阅读过程在写作过程完成之前终止。
答案 0 :(得分:2)
如果某些pipe(2)的阅读结尾为close(2),则write(2)将获得SIGPIPE
signal(7)。另请阅读pipe(7)。
当管道缓冲区变满时,它们会得到SIGPIPE
。
在yes | ./readstdin
命令中,yes
命令获得一个SIGPIPE
信号。只需在终端中尝试yes
,它就会无限期地输出输出 ,直到你杀死它为止。
在cat file | ./readstdin
命令中,可能会发生(file
非常小,少于sysconf(_POSIX_PIPE_BUF)
字节,可能是4096字节)cat
命令是close(2)
- STDOUT_FILENO
描述符,并且管道仍未满。然后cat
可能无法获得任何SIGPIPE
。
答案 1 :(得分:1)
正常进程关闭输入流,导致SIGPIPE。在手册页中,它提到-m
停止读取,并且“确保标准输入位于退出前最后一个匹配行之后”。所以它实际上并没有关闭流。你可以这样证明:
cat file | (grep -m1 z && grep -m1 c)
您将在第一个c
之后获得第一个z
,这有时很有用。在最后一个grep退出之后,流没有地方可以去,因此它未被读取并且整组命令退出。你可以证明:
(while true; do echo z; sleep 1; done) | grep -m3 z
(while true; do echo z; sleep 1; done) | grep --line-buffered z | head -3