这是随机生成10个字符的密码一个管道命令:这个管道为什么终止?
cat /dev/urandom | base64 | head -c 10
我的问题是cat /dev/urandom | base64
是一个无限的输出流,这将无法自动停止。但为什么追加head -c 10
使整个管道终止?我假设cat
,base64
和head
是3个分离过程,head
怎么能终止cat
?
这是随机生成10个字符的密码一个管道命令:这个管道为什么终止?
cat /dev/urandom | base64 | head -c 10
我的问题是cat /dev/urandom | base64
是一个无限的输出流,这将无法自动停止。但为什么追加head -c 10
使整个管道终止?我假设cat
,base64
和head
是3个分离过程,head
怎么能终止cat
?
base64
输出10个字节后,head
获得足够的输入和退出。当前者尝试输出更多字节时,它将收到SIGPIPE signal,因此也会退出。出于同样的原因,cat
将依次退出。
head
在读取所需数量后关闭输入文件。当管道从一侧关闭时,另一侧出现写错误;这导致base64
关闭,这又导致cat
关闭。
管道的工作方式是连接一个进程A的输出到B的输入端的连接可以被打破,当
由于这两种情况如此常见,所以处理已移到C标准库中。
谢谢,但“处理已移到C标准库”是什么意思? A和B是通过shell来终止的,而不是它们检测到输入/输出的关闭并自行停止? – Dagang 2012-04-05 15:31:44
当B关闭其管道侧时,A将收到信号。标准库c.lib('fprintf()','open()','read()',...)的I/O例程中的代码处理信号,函数调用将返回errno EPIPE =“损坏的管道”。 – 2012-04-05 15:36:53
@AaronDigulla,我不同意。我不知道任何安装了SIGPIPE处理程序的C库,我的实验也没有提示它。事实上,SIGPIPE交付后会导致任何未安装处理程序的程序(即所有程序的99%)退出。 – 2012-04-05 18:57:56
可能值得一提的是,'head'完全可以得到任何输入的是'base64'在输入达到一定数量后写入输出,也就是缓冲区满时。如果要阅读直到EOF,它将永远阅读,而“头”永远不会有任何裂缝。所以有一个类似的管道,比如'cat/dev/urandom |总和| head -c 10'会表现不同,因为'sum'等待EOF。 – 2012-04-05 16:23:32
s /得到写入错误/收到SIGPIPE/ – 2012-04-05 18:38:41
Rob的评论*非常相关。如果进程继承SIGPIPE处理程序或忽略SIGPIPE(例如,如果它在较早的python解释程序子进程模块下运行)并且不检查写入错误,则它不会终止。写入错误和接收SIGPIPE之间存在巨大的差异,忽略这两个问题的程序可能会无限期地运行。 – 2012-04-05 19:55:13