How does it happen that if I enter:
cat /dev/urandom
then it will take forever to output data, but with:
cat /dev/urandom | head -c 10
the output ends after 10 random bytes, does head
instructs somehow cat
to finish its output?
The cat
will get a SIGPIPE
signal when it tries to write to a pipe with no readers (when head
terminates, it automatically closes its stdin, which is also the only open handle to the reading end of the pipe).
If you somehow get another handle to the reading end of the pipe, the cat will not finish, but block after it fills up the pipe buffer:
(Linux-only example):
cat /dev/urandom 3</dev/stdout | head -c 10 > /tmp/junk
<staying there until you ^C>
Also, if you get cat
to ignore the SIGPIPE
signal, the write which would've generated the SIGPIPE
signal will simply fail, setting the errno
to EPIPE
= Broken pipe
^1:
{ trap '' PIPE; cat /dev/urandom; } | head -c 10 >/tmp/junk
cat: write error: Broken pipe
The head
process has no hand in all this; it doesn't signal, instructs or care at all about the cat
; it just reads whatever it needs and then just exits, leaving it to the operating system to take care of all the rest.
^1 This latter behaviour is (quite annoyingly) the default for python scripts:
python -c 'while 1: print("hello")' | head -n2
hello
hello
Traceback (most recent call last):
File "<string>", line 1, in <module>
IOError: [Errno 32] Broken pipe