Question

When is the piped program terminated and who controls this termination process? I've read Bash: why the pipe is terminated? but it covers this question only partially. After trying to answer this question myself I made a couple of examples to see their outputs. And this one I don't understand: (a.sh):

#!/bin/bash

echoerr() { echo $@ 1>&2; }

echoerr a.sh started

sleep 1
echo 1

sleep 1
echo 2

sleep 1
echo 3

sleep 1 # Line 1
echo 4  # Line 2

echoerr a.sh finished

And I run it as ./a.sh | head -3. The output is:

a.sh started
1
2
3

From the output I understood that ./a.sh was terminated with SIGPIPE signal after reading first 3 lines of input because no more data was needed. But when I remove either Line 1 either Line 2 the output changes to the following:

a.sh started
1
2
3
a.sh finished

So my question are:

  • What is the policy of terminating piped program?
  • Why does Line 1 affect program behaviour?
  • Why does Line 2 affect program behaviour?
Was it helpful?

Solution

As you've said, you shell script will die if it attempts to write to a closed pipe. It won't if it doesn't.

If you remove the second line, a.sh doesn't attempt to write to its stdout after echo 3, so it has no reason to fail.

Removing the first line might not get you the same result every time you run your test. There's a timing issue. If the last two echo statements are processed before head attempts to read from it's input (and terminate because it's reached 3 lines), then a.sh won't get a broken pipe error. If the timing is such that head does a read in between the two echos, then a.sh will get the pipe error, and die.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top