I have the following bash code (running on Red Hat) that is exiting when I enable set -o errexit
and the variable in the code is empty, BUT works fine when the variable is set; the code is designed to test if a screen session matching .monitor_*
exists, and if so do something.
I have the following turned on:
set -o errexit set -x xtrace; PS4='$LINENO: '
If there is a session matching the above pattern it works; however, if nothing matches it just exits with no information other than the following output from xtrace
someuser:~/scripts/tests> ./if_test.sh + ./if_test.sh + PS4='$LINENO: ' 4: set -o errexit 5: set -o pipefail 6: set -o nounset 88: /usr/bin/ls -lR /var/run/uscreens/S-storage-rsync 88: grep '.monitor_*' 88: awk '{ print $9 }' 88: /usr/bin/grep -Ev 'total|uscreens' 8: ms=
I tested the command I am using to set the ms
var and it agrees with the xtrace output, it’s not set.
someuser:~/scripts/tests> test -n "${mn}" + test -n ''
I have tried using a select statement and got the same results… I can’t figure it out, anyone able to help? Thanks.
I read through all the possible solution recommendations, nothing seems to address my issue.
The code:
#!/usr/bin/env bash set -o xtrace; PS4='$LINENO: ' set -o errexit set -o pipefail set -o nounset ms="$(/usr/bin/ls -lR /var/run/uscreens/S-"${USER}" | /usr/bin/grep -Ev "total|uscreens" | grep ".monitor_*" | awk '{ print $9 }')" if [[ -z "${ms}" ]]; then echo "Handling empty result" elif [[ -n "${ms}" ]]; then echo "Handling non-empty result" fi
The following answer was proposed: Test if a variable is set in bash when using “set -o nounset”; however, it doesn’t address the issue at all. In my case the variable being tested is set and as stated in my detail, it’s set to ""
, or nothing. Thank you; however, it doesn’t help.
It really seems to be the variable declaration that it isn’t liking.
ms="$(/usr/bin/ls -lR /var/run/uscreens/S-"${USER}" | /usr/bin/grep -Ev "total|uscreens" | grep ".monitor_*" | awk '{ print $9 }')"
Advertisement
Answer
- You’re running
set -o pipefail
, so if any component in a pipeline has a nonzero exit status, the entire pipeline is treated as having a nonzero exit status. - Your pipeline runs
grep
.grep
has a nonzero status whenever no matches are found. - You’re running
set -o errexit
(akaset -e
). Witherrexit
enabled, the script terminates whenever any command fails (subject to a long and complicated set of exceptions; some of these are presented in the exercises section of BashFAQ #105, and others touched on in this excellent reference).
Thus, when you have no matches in your grep
command, your script terminates on the command substitution running the pipeline in question.
If you want to exempt a specific command from set -e
‘s behavior, the easiest way to do it is to simply append ||:
(shorthand for || true
), which marks the command as “checked”.