Hi Bash Experts!
Every couple of years I stumble upon weird behavior in bash scripts, which I cannot explain, and every time it was due to documented bash behavior. Can, please, someone explain to me why the following script terminates?
I've tried this on Ubuntu 22.04 and Ubuntu 20.04 with same results -- see "Observations" at the end of the script.
Thanks!
=== #!/bin/bash
set -euf -o pipefail
print_test () { local count="$1" while [ $count -ge 0 ]; do if [ x"$(echo a)" = x"a" ]; then echo a fi count=$(($count - 1)) done }
main () { local count=1 while print_test "$count" | grep -q "a"; do echo "$count: OK" count=$(($count + 1)) done echo "$count: BAD" }
main exit 1
# Observations: # 1. With "if" in print_test BAD happens on around count "2" # 2. Without "if" in print_test BAD happens around count "80" # 3. Changing "grep -q" to "grep" makes the problem go away. # 4. Removing -o pipefail makes the problem go away. # 5. While loop in "main" isn't required, but makes reproduction easier. ===
-- Maxim Kuvyrkov https://www.linaro.org
On 07/03/2023 18:40, Maxim Kuvyrkov wrote:
Hi Bash Experts!
Every couple of years I stumble upon weird behavior in bash scripts, which I cannot explain, and every time it was due to documented bash behavior. Can, please, someone explain to me why the following script terminates?
I've tried this on Ubuntu 22.04 and Ubuntu 20.04 with same results -- see "Observations" at the end of the script.
Thanks!
=== #!/bin/bash
set -euf -o pipefail
print_test () { local count="$1" while [ $count -ge 0 ]; do if [ x"$(echo a)" = x"a" ]; then echo a fi count=$(($count - 1)) done }
main () { local count=1 while print_test "$count" | grep -q "a"; do echo "$count: OK" count=$(($count + 1)) done echo "$count: BAD" }
main exit 1
# Observations: # 1. With "if" in print_test BAD happens on around count "2" # 2. Without "if" in print_test BAD happens around count "80" # 3. Changing "grep -q" to "grep" makes the problem go away. # 4. Removing -o pipefail makes the problem go away.
# 5. While loop in "main" isn't required, but makes reproduction easier.
-- Maxim Kuvyrkov https://www.linaro.org
grep -q is exiting as soon as a match is found. print_test is continuing to write to the now-broken pipe and gets killed by a SIGPIPE.
Thanks, Ian!
-- Maxim Kuvyrkov https://www.linaro.org
On Mar 8, 2023, at 2:51 PM, Ian Abbott abbotti@mev.co.uk wrote:
On 07/03/2023 18:40, Maxim Kuvyrkov wrote:
Hi Bash Experts! Every couple of years I stumble upon weird behavior in bash scripts, which I cannot explain, and every time it was due to documented bash behavior. Can, please, someone explain to me why the following script terminates? I've tried this on Ubuntu 22.04 and Ubuntu 20.04 with same results -- see "Observations" at the end of the script. Thanks! === #!/bin/bash set -euf -o pipefail print_test () { local count="$1" while [ $count -ge 0 ]; do if [ x"$(echo a)" = x"a" ]; then echo a fi count=$(($count - 1)) done } main () { local count=1 while print_test "$count" | grep -q "a"; do echo "$count: OK" count=$(($count + 1)) done echo "$count: BAD" } main exit 1 # Observations: # 1. With "if" in print_test BAD happens on around count "2" # 2. Without "if" in print_test BAD happens around count "80" # 3. Changing "grep -q" to "grep" makes the problem go away. # 4. Removing -o pipefail makes the problem go away.
# 5. While loop in "main" isn't required, but makes reproduction easier.
-- Maxim Kuvyrkov https://www.linaro.org
grep -q is exiting as soon as a match is found. print_test is continuing to write to the now-broken pipe and gets killed by a SIGPIPE.
-- -=( Ian Abbott abbotti@mev.co.uk || MEV Ltd. is a company )=- -=( registered in England & Wales. Regd. number: 02862268. )=- -=( Regd. addr.: S11 & 12 Building 67, Europa Business Park, )=- -=( Bird Hall Lane, STOCKPORT, SK3 0XA, UK. || www.mev.co.uk )=-