tee ... | : is still a process holding the read-end of the pipeline set up by the shell, the other end of which
tee is writing to. It's just that
: exits immediately, which stops it from reading from the pipe. (For the simultaneous action of the pipeline to work, the shell has to spawn a new process for each part of the pipeline, even if it's just to process the no-op
:. In your example, that process would run the
if statement in the last part of the pipe, and then eventually exit after "running" the
The usual behaviour is that when the reader of a pipe exits (the read-end file descriptors are closed), the writer gets the SIGPIPE signal on the next write, and that causes it to exit.
That's usually what you want since it means that if the right-hand side of a pipeline exits, the left-hand side also exits, and doesn't hang around continuing a potentially long task uselessly. Or (worse) get stuck helplessly trying to write to a blocked pipe that doesn't admit any writes because the data has nowhere to go.
tee it doesn't look like there's any exception in the POSIX specification; the part that goes nearest is a mention of write errors to file operands:
If a write to any successfully opened file operand fails, writes to other successfully opened file operands and standard output shall continue, but the exit status shall be non-zero.
If SIGPIPE is ignored, the implementations I tested continue past the
EPIPE error that then gets returned from the
The GNU coreutils version of
tee has the
--output-error options to control what it does when a write fails:
The default operation when
--output-error is not specified, is to exit immediately on error writing to a pipe, and diagnose errors writing to non pipe outputs.
Though the way it exits is via the SIGPIPE, so starting
tee with the signal ignored it makes it not exit.
And the default with
-p is the
warn-nopipe mode, which is described as "diagnose errors writing to any output not a pipe", as opposed to the other options that make it exit. Under the hood, it also ignores the SIGPIPE signal and then stops trying to write to the pipe.
So, with the GNU version at least, you can use
tee -p ... | ... to prevent it from exiting when the pipe reader exits. Alternatively, you could arrange for the right-hand side program to be something mimicking a black hole instead, e.g.
cat > /dev/null (which still reads and writes everything it gets, but the kernel eventually then ignores the data written to