Return code before grep part 3 and the pipefail hack

whenever you do

mycmd | grep mytext

the return code of command got lost, $? point to the return code of grep.  Back in time I posted https://laurentschneider.com/wordpress/2009/05/return-code-before-grep.html

( 
  ( 
    (
      mycmd
      echo $? >&3
    ) |grep mytext >&4 
  ) 3>&1 |(read x;exit $x) 
)4>&1

this did work like a charm for decades.

But earlier this year I found this sexy syntax

mycmd > >(grep mytext)

While it may abuse your memory, especially on legacy/ancient operating systems, it is more understandable. A little bit. Maybe. YMMV.

Last week I discovered also, while ansiblelinting my code

set -o pipefail
mycmd | grep mytext

It looks better but it is a disgusting hack. I tested a bit and very quickly decided to add

skip_list:
- 'risky-shell-pipe'

in my .ansible-lint file.

pipefail has an annoying handling of SIGPIPE.

# ( set -o pipefail; head -c 95698 /tmp/xxx | grep -q .; echo $? )
141
# ( set -o pipefail; head -c 95698 /tmp/xxx | grep -q .; echo $? )
0
# ( set -o pipefail; head -c 95698 /tmp/xxx | grep -q .; echo $? )
0
# ( set -o pipefail; head -c 95698 /tmp/xxx | grep -q .; echo $? )
0

Random absolutely unusable stuff… avoid!

SIGPIPE is documented as :

On a last note, pipes must have a reader and a writer. If a process tries to write to a pipe that has no reader, it will be sent the SIGPIPE signal from the kernel.

so when head stops writing, grep may no longer read and the pipe may get a death signal. But it is not consistent.

Leave a Reply

Your email address will not be published. Required fields are marked *