11

I am learning how to efficiently use different set options in my script and came across set -u that appears to be perfect for exiting my script if a variable does not get set properly (ex. deleting users). According to the man page, set -u and set -e does the following...

-e  Exit immediately if a command exits with a non-zero status.
-u  Treat unset variables as an error when substituting.

I created a test script to test this functionality, but it does not appear to be working as expected. Perhaps someone could better explain my issue to me and where I am mis-interpreting? Test script is below. Thank you.

set -e
set -u
testing="This works"
echo $?
echo ${testing}
testing2=
echo $?
echo ${testing2}
testing3="This should not appear"
echo $?
echo ${testing3}

I expect the script to display 0 and "This works", and then fail as ${testing2} is not set.

Instead I am displayed 0 and "This works", follow by 0 and then 0 This should not appear

Can anyone provide some knowledge? Thank you.

  • 1
    So followup... is there any way to make setting a variable to the null string illegal/raise an error? I'm guessing not. – Luke Davis Feb 23 '18 at 6:32
9

From "man Bash":

A parameter is set if it has been assigned a value. The null string is a valid value. Once a variable is set, it may be unset only by using the unset builtin command.

When you do testing2= you are setting the variable to the null string.

Change that to unset testing2 and try again.


The set -e does not help in this case as an assignment never has an exit code of 1. Try this to see that the last command executed (the assignment) has an exit code of 0, or read this question:

$ false; a=""; echo $?
0

And I also believe that the use of set -e is more a problem that a solution.

What may get an error with the use of unset variables is set -u:

#!/bin/bash
set -u
testing="This works"
echo ${testing}
unset testing2
echo ${testing2}
testing3="This should not appear"
echo ${testing3}

Will output:

$  ./script.sh
This works
./script.sh: line 9: testing2: unbound variable
3

testing2= sets the testing2 variable to an empty string; the variable actually is set.

However if you were to run echo $testing99 in an interactive Bash shell (without setting errexit, i.e., set -e), you would get an error:

bash: testing99: unbound variable

Aside

While testing scripts just now, I discovered that an interactive shell does not always exit when attempting to expand a variable that hasn’t been set while a non-interactive shell (running a shell script) always exits. According to the POSIX man page for set:

-u The shell shall write a message to standard error when it tries to expand a variable that is not set and immediately exit. An interactive shell shall not exit.

An interactive Bash shell won’t exit unless errexit has also been set. On the other hand, an interactive dash shell won’t exit – even if set -e has previously been run.

  • If dash does not exit with set -e; set -u; unset aa; echo $aa, then dash is wrong. – schily Mar 8 '16 at 23:03
  • @schily When I first noticed this, I figured that the dash authors knew better than me and that there may have been some ambiguity in the POSIX specifications but having re-checked pubs.opengroup.org/onlinepubs/9699919799/utilities/…, I agree that looks like a bug, alright. – Anthony Geoghegan Mar 8 '16 at 23:53
  • There is a simple rule: when both Korn Shell and Bourne Shell agree and another shell implementation has a deviation, then the other shell behaves incorrectly. – schily Mar 9 '16 at 9:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.