why [] test makes this script to fail?
Please consider these two scripts:
run.sh:
#!/bin/bash
set -euo pipefail
. "$(dirname $(realpath $BASH_SOURCE))"/init-sudo-script.sh
init-sudo-script.sh
[ ${#BASH_SOURCE[@]} -eq 1 ]
&& echo "must be sourced by another script."
&& exit 10
[ $EUID -ne 0 ]
&& echo "must be executed as root."
&& exit 20
This is correct and it is what I expect to happen:
$ ./run.sh
must be executed as root.
$ echo $?
20
But this I can’t understand:
$ sudo ./run.sh
$ echo $?
1
I know the problem is [ $EUID -ne 0 ]
because the script works when I remove it.
I also understand set -e
makes the script to exit on any error.
What I don’t understand is why the first guard condition ([ ${#BASH_SOURCE[@]} -eq 1 ]
) doesn’t exit with 1 when it fails but the second does.
Does anybody understand what is happening here?
===UPDATE===
I found a way to make it works as I expect:
if [ $EUID -ne 0 ]; then
echo "must be executed as root."
&& exit 20
fi
I would leave this behind but I’m investing on getting better in Bash. So if anyone can clarify what’s going on I’d appreciate to hear.
I also understand
set -e
makes the script to exit on any error.
Not "on any error". There are exceptions, one of them is:
The shell does not exit if the command that fails is […] part of any command executed in a
&&
or||
list except the command following the final&&
or||
, […]
(source)
If [ ${#BASH_SOURCE[@]} -eq 1 ]
fails then the shell will not exit because of set -e
.
Similarly if [ $EUID -ne 0 ]
fails then the shell will not exit because of set -e
. But it will exit just after because the script ends, i.e. because there is nothing more to execute. And then the exit status of the script will be the exit status of the last command executed; and it happens to be the failing [
. This is why you get 1
.
Place :
(a no-op command that always succeeds) at the end of init-sudo-script.sh
and re-run your tests. sudo ./run.sh
will return 0
because the last command will be :
.
Your updated code with if
is different because the exit status from if
is:
[…] zero if no condition tested true.
(source)