Debugging scripts, what is the difference between -x to set -euxo pipefail?

9,863

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.

Share:
9,863
Admin
Author by

Admin

Updated on September 18, 2022

Comments

  • Admin
    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
    JOKER almost 7 years
    I 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
    Arkadiusz Drabczyk almost 7 years
    If 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
    JOKER almost 7 years
    I meant to say I'm not sure if you suggest me to use or not using the e argument.
  • Arkadiusz Drabczyk
    Arkadiusz Drabczyk almost 7 years
    It 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
    JOKER almost 7 years
    Oh, I'm not sure this way, so I'd better remove it.
  • Patrice M.
    Patrice M. about 5 years
    Can you maybe expand the answer, explaining why -u is recommended in this context ?
  • karthik v
    karthik v over 4 years
    set -u Treat unset variables as an error, and immediately exit.