Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash while loop stops unexpectedly

I'm analyzing two scripts with some behaviour I don't understand:

#/bin/bash
tijd=${1-60}
oud=`ls -l $MAIL`
while : ; do
   nieuw=`ls -l $MAIL`
   echo $oud $nieuw
   sleep $tijd
done | { read a b rest ; echo $a ; echo $b ; echo $rest ; }

The while loop in this script stops after one iteration.

#/bin/bash
tijd=${1-60}
oud=`ls -l $MAIL`
while : ; do
   nieuw=`ls -l $MAIL`
   echo $oud $nieuw
   sleep $tijd
done | cat

The while loop in this script is infinite.

What is the difference? I think it's something with the pipe and the brackets but I can't explain it.

like image 350
wardva Avatar asked Oct 19 '22 11:10

wardva


1 Answers

Your loop with read after pipe is terminating after first iteration because of invocation of SIGPIPE signal which happens LHS of pipe writes to a pipe whose output is not read as there is no while loop around read on RHS). YOur example with cat doesn't exit because cat continuously reads from input where as read terminates after reading one line.

To understand this behavior first reduce your example:

while : ; do pwd; done | { read -r line; echo $line; }
/Users/admin

So read terminated after first line. To verify this enable pipefail using:

set -o pipefail

and check exit status:

while : ; do pwd; done | { read -r line; echo "$line"; }
echo $?
141

Exist status 141 is due to SIGPIPE.


To fix this now change your read on RHS of pipe inside a while loop:

while : ; do pwd; sleep 5; done | { while read -r line; do echo "$line"; done; }
/Users/admin
/Users/admin
/Users/admin

And now you will not see command exiting at all since while read is continuously capturing all the data from LHS of pipe.

like image 124
anubhava Avatar answered Oct 22 '22 01:10

anubhava