agc agc - 5 months ago 10
Linux Question

Counter loop piped to grep seems unexpectedly random

Experiment to make grep stop a while loop at 5 iterations, so that /tmp/foo should only be 5 lines long:

n=1
while [ $n -le 2000 ]
do
echo $n
n=$(( $n + 1 ))
done | tee /tmp/foo | grep -q ^5


Check count:

wc -l < /tmp/foo


Outputs:

34


Repeated runs of the above return different numbers most every time, but it's not very random -- running the above 5000 times in bash results in about 1500 9s for example, running it 5000 times in dash results in 157 106s.

These results seem more interesting than the initial experiment. What's happening in this code?

Answer

Pipes are asynchronous. While tee will exit the first time it tries to write to its end of the pipe after grep exits and closes its end, there is no way to know how many lines tee will write before grep actually does so. It's entirely up to the OS scheduler.