:> 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 +++
From man 2 write
:
EPIPE
fd is connected to a pipe or socket whose reading end is closed. When this happens the writing process will also receive a SIGPIPE signal.
So the processes die right to left. head
exits on its own, tee
gets killed when it tries to write to the pipeline the first time after head
has exited. The same happens with yes
after tee
has died.
tee
can write to the pipeline until the buffers are full. But it can write as much as it likes to a file. It seems that my version of tee
writes the same block to stdout
and the file.
head
has 8K in its (i.e. the kernel's) read buffer. It reads all of it but prints only the first 10 lines because that's its job.
tee
, not the kernel's buffer. If we do something likeyes | strace tee output | (sleep 1; head)
, we'll see thattee
writes more than that to the pipe before blocking on the write, 64 k on my system (that seems to be the pipe buffer size according to the man page). In the non-sleep case, it's just thathead
gets to run immediately, and closes the pipe. – ilkkachu Jan 14 '18 at 15:54tee
is unbuffered. There are two sets of buffers downstream of it, a kernel buffer that comprises the pipe and the stdin buffering in the standard library of thehead
process. ikkachu's command line, which I was just about to suggest, demonstrates that the pipe buffer itself can take more than 8KiB. The 8KiB gulp thathead
takes is the GNU C run-time library filling up the internal buffer in the stdin stream. (Run this on a BSD, and you'll see the BSD C RTL using different stdin buffer sizes.) – JdeBP Jan 14 '18 at 16:09