Debugging scripts, what is the difference between -x to set -euxo pipefail?
First, I'm afraid that explanation of -o
option served by http://explainshell.com is not entirely correct.
Given that set
is a bulit-in
command, we can see its documentation with help
by executing help set
:
-o option-name
Set the variable corresponding to option-name:
allexport same as -a
braceexpand same as -B
emacs use an emacs-style line editing interface
errexit same as -e
errtrace same as -E
functrace same as -T
hashall same as -h
histexpand same as -H
history enable command history
ignoreeof the shell will not exit upon reading EOF
interactive-comments
allow comments to appear in interactive commands
keyword same as -k
monitor same as -m
noclobber same as -C
noexec same as -n
noglob same as -f
nolog currently accepted but ignored
notify same as -b
nounset same as -u
onecmd same as -t
physical same as -P
pipefail the return value of a pipeline is the status of
the last command to exit with a non-zero status,
or zero if no command exited with a non-zero status
posix change the behavior of bash where the default
operation differs from the Posix standard to
match the standard
privileged same as -p
verbose same as -v
vi use a vi-style line editing interface
xtrace same as -x
As you can see -o pipefail
means:
the return value of a pipeline is the status of the last command to exit with a non-zero status, or zero if no command exited with a non-zero status
But it doesn't say: Write the current settings of the options to standard output in an unspecified format.
Now, -x
is used for debugging as you already know it and -e
will
stop executing after the first error in the script. Consider a script
like this:
#!/usr/bin/env bash
set -euxo pipefail
echo hi
non-existent-command
echo bye
The echo bye
line will never be executed when -e
is used because
non-existent-command
does not return 0:
+ echo hi
hi
+ non-existent-command
./setx.sh: line 5: non-existent-command: command not found
Without -e
the last line would be printed because even though an
error happened we didn't tell Bash
to automatically exit:
+ echo hi
hi
+ non-existent-command
./setx.sh: line 5: non-existent-command: command not found
+ echo bye
bye
set -e
is often put at the top of the script to make sure that the
script will be stopped when the first error is encountered - for
example, if downloading a file failed it doesn't make sense to extract
it.
Admin
Updated on September 18, 2022Comments
-
Admin over 1 year
The main way I know to debug scripts is adding
-x
to the shabang (#!/bin/bash -x
).I recently came across a new way, adding
set -euxo pipefail
right under the shabang, as in:#!/bin/bash set -euxo pipefail
What is the main difference between the two ways of debugging? Are there times you would prefer one above the other?
As a freshman, after reading here, I couldn't extract such conclusion.
-
JOKER almost 7 yearsI read the answer but I'm not sure I get this: What is the syntax you recommend using (I believe it's slightly different, like this
set -uxo pipefail
). -
Arkadiusz Drabczyk almost 7 yearsIf you mean
set -e
it just will cause will cause script terminate on error. In your example it's only one of many options together with-uxo pipefail
. -
JOKER almost 7 yearsI meant to say I'm not sure if you suggest me to use or not using the
e
argument. -
Arkadiusz Drabczyk almost 7 yearsIt depends on your requirements. It's not set by default so it's up to the author. If you're sure that all commands used in the script would always return
0
on success and non-zero on failure then-e
is useful but as everything else it should be used with caution. -
JOKER almost 7 yearsOh, I'm not sure this way, so I'd better remove it.
-
Patrice M. about 5 yearsCan you maybe expand the answer, explaining why -u is recommended in this context ?
-
karthik v over 4 yearsset -u Treat unset variables as an error, and immediately exit.