I encountered a somewhat strange behavior of BASH infinite loops which outputs are pipelined to another processes. Namely, I run these two commands:
(while true; do echo xxx; done) | head -n 1
(while true; do date; done) | head -n 1
The first one exits instantly while the second one does not (and I assume it would run forever without being killed). I also tried an implicit infinite loop:
yes | head -n 1
and it also exits by itself. An appropriate line of output is immediately printed on the screen in each case. I am just curious what determines if such a commmand will finish.
Press Ctrl + Z to stop the job, and send it to the background.
There is no way to stop an infinite loop. However, you can add a condition inside of the loop that causes it to break, or you can call the exit() function inside of the loop, which will terminate your program.
In Bash scripting, a break statement helps provide control inside loop statements. Instead of waiting until the end condition, a break statement helps exit from a loop before the end condition happens.
break command is used to terminate the execution of for loop, while loop and until loop.
When head
exits, the standard output of the parenthesized expression is closed. If an external command, like date
, is used, the loop hangs. If an internal command of bash is used, like echo
, the loop exits. For proof, use
(while true; do /bin/echo xxx; done) | head -n 1
and it will hang. If you use
(while true; do date; echo $? 1>&2; sleep 1; done) | head -n 1
you will see that on the second round, the date
command returns an error exit code, i.e. something other but zero. Bash obviously does this not take as serious as when an internal command gets into problems. I wonder if this is intended or rather a bug in bash.
To make sure the loop is exited, this seems to work:
(set -e; while true; do date ; done) | head -n 1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With