CrackOps
Interview PrepTracksLinuxAWS LabSoonInterview RoomSoon
Sign inStart free
CrackOps

Interview prep for the people who keep production up.

[email protected]
ProductInterview PrepTracksDashboardInterview Room
RolesDevOpsSREPlatformCloud
CompanyAboutContactPrivacyTerms
© CrackOps
Linux / Environment & Shell / set

set

Shell options: set -euo pipefail, set -x and friends

Intermediatescriptingshelldebugging

set changes how the shell itself behaves: -e stops a script on the first failing command, -u treats unset variables as errors, -o pipefail makes a pipeline fail if any part fails, and -x prints every command as it runs. It also sets positional parameters and, with no arguments, lists every variable and function.

Syntaxset [-euxva] [-o OPTION] [+euxva] [+o OPTION] [-- ARG...]

Watch it run

A deploy script kept going after a failed step and shipped a broken build. See what each option catches.

devops@devops-lab: ~ — zsh — 96×28
➜ ~
Step 1 of 5
bash -c 'cp app.tar.gz /nonexistent/; echo "deploying anyway"'; echo "exit=$?"

By default bash ignores the failure and carries on, and the script even exits 0 because the last command succeeded.

Anatomy of a command

$
commandset

Bash builtin that changes options of the current shell. A minus turns an option on, a plus turns it off.

How it works

Shell options are flags inside the bash process; $- shows the single-letter ones that are on (hB for a typical script, himBHs for an interactive shell). With errexit (-e), after each simple command bash checks the exit status and, if it's non-zero and the command isn't part of a condition (if, while, until, an operand of && or ||, or negated with !), it exits with that status. Commands inside a function called from a condition are also exempt, which surprises people. nounset (-u) makes expanding an unset variable print 'unbound variable' and exit. ${VAR:-default} and ${VAR-} are allowed. pipefail changes a pipeline's exit status from the last command's to the rightmost non-zero one. xtrace (-x) prints each command after expansion to stderr, prefixed with PS4 ('+ '). set -- args replaces $1, $2... and $#. With no arguments, set prints every shell variable and function, exported or not. These options are per process: a child script starts with defaults unless SHELLOPTS is exported or it sets them itself.

Options you'll actually use

-e (errexit)Exit on the first failing command (outside conditions)
-u (nounset)Error on use of an unset variable
-o pipefailPipeline fails if any command in it fails
-x (xtrace)Print each command, expanded, to stderr before running it
-v (verbose)Print each line as it's read, before expansion
-a (allexport)Export every variable assigned
-n (noexec)Parse only, don't run: a syntax check
-C (noclobber)> refuses to overwrite existing files (use >| to force)
+x, +e ...Turn an option off again
set -oList all options with on/off
set -- a b cSet positional parameters $1 $2 $3
set (no args)Print all variables and functions

Common mistakes

Relying on set -e to catch every failure

It's suspended inside if/while conditions, && / || chains and functions called from them, and pipelines report only the last command without pipefail.

set -euo pipefail, plus explicit checks: cmd || { echo 'cmd failed' >&2; exit 1; }
grep pattern file | wc -l under set -eo pipefail

grep exits 1 when nothing matches, so 'zero matches' kills the script.

{ grep pattern file || true; } | wc -l # or grep -c pattern file || true
set -x in a CI job that handles tokens

Every expanded command is printed, secrets included, into build logs.

set +x before secret handling, or only trace locally with bash -x
Typing set -e in your interactive shell to 'be safe'

The next command that fails (a typo, a grep with no match) exits your shell or SSH session.

Use it in scripts only

Interview questions

Practice

Try these on a Linux machine of your own. Each task has a hint and a solution.

  1. 1

    Write a two-line script ~/strict.sh that uses set -euo pipefail and then reads an unset variable. Run it and check the exit code.

  2. 2

    Trace ~/app/scripts/deploy.sh with version 9.9.9 and find the tar command it runs.

  3. 3

    Show that without pipefail a failing grep is hidden by wc, and with it the pipeline fails.

  4. 4

    In bash, list which of errexit, nounset, pipefail and xtrace are on in your interactive shell.

Related commands

bash: exit codesExit codes, $?, set -euo pipefail and trapunsetRemove variables and functions from the shellenvShow the environment, or run a command with a changed onesourceRun a file's commands in the current shell
PreviousechoNextunset
Linux / Environment & Shell / set

set

Shell options: set -euo pipefail, set -x and friends

Intermediatescriptingshelldebugging

set changes how the shell itself behaves: -e stops a script on the first failing command, -u treats unset variables as errors, -o pipefail makes a pipeline fail if any part fails, and -x prints every command as it runs. It also sets positional parameters and, with no arguments, lists every variable and function.

Syntaxset [-euxva] [-o OPTION] [+euxva] [+o OPTION] [-- ARG...]

Watch it run

A deploy script kept going after a failed step and shipped a broken build. See what each option catches.

devops@devops-lab: ~ — zsh — 96×28
➜ ~
Step 1 of 5
bash -c 'cp app.tar.gz /nonexistent/; echo "deploying anyway"'; echo "exit=$?"

By default bash ignores the failure and carries on, and the script even exits 0 because the last command succeeded.

Anatomy of a command

$
commandset

Bash builtin that changes options of the current shell. A minus turns an option on, a plus turns it off.

How it works

Shell options are flags inside the bash process; $- shows the single-letter ones that are on (hB for a typical script, himBHs for an interactive shell). With errexit (-e), after each simple command bash checks the exit status and, if it's non-zero and the command isn't part of a condition (if, while, until, an operand of && or ||, or negated with !), it exits with that status. Commands inside a function called from a condition are also exempt, which surprises people. nounset (-u) makes expanding an unset variable print 'unbound variable' and exit. ${VAR:-default} and ${VAR-} are allowed. pipefail changes a pipeline's exit status from the last command's to the rightmost non-zero one. xtrace (-x) prints each command after expansion to stderr, prefixed with PS4 ('+ '). set -- args replaces $1, $2... and $#. With no arguments, set prints every shell variable and function, exported or not. These options are per process: a child script starts with defaults unless SHELLOPTS is exported or it sets them itself.

Options you'll actually use

-e (errexit)Exit on the first failing command (outside conditions)
-u (nounset)Error on use of an unset variable
-o pipefailPipeline fails if any command in it fails
-x (xtrace)Print each command, expanded, to stderr before running it
-v (verbose)Print each line as it's read, before expansion
-a (allexport)Export every variable assigned
-n (noexec)Parse only, don't run: a syntax check
-C (noclobber)> refuses to overwrite existing files (use >| to force)
+x, +e ...Turn an option off again
set -oList all options with on/off
set -- a b cSet positional parameters $1 $2 $3
set (no args)Print all variables and functions

Common mistakes

Relying on set -e to catch every failure

It's suspended inside if/while conditions, && / || chains and functions called from them, and pipelines report only the last command without pipefail.

set -euo pipefail, plus explicit checks: cmd || { echo 'cmd failed' >&2; exit 1; }
grep pattern file | wc -l under set -eo pipefail

grep exits 1 when nothing matches, so 'zero matches' kills the script.

{ grep pattern file || true; } | wc -l # or grep -c pattern file || true
set -x in a CI job that handles tokens

Every expanded command is printed, secrets included, into build logs.

set +x before secret handling, or only trace locally with bash -x
Typing set -e in your interactive shell to 'be safe'

The next command that fails (a typo, a grep with no match) exits your shell or SSH session.

Use it in scripts only

Interview questions

Practice

Try these on a Linux machine of your own. Each task has a hint and a solution.

  1. 1

    Write a two-line script ~/strict.sh that uses set -euo pipefail and then reads an unset variable. Run it and check the exit code.

  2. 2

    Trace ~/app/scripts/deploy.sh with version 9.9.9 and find the tar command it runs.

  3. 3

    Show that without pipefail a failing grep is hidden by wc, and with it the pipeline fails.

  4. 4

    In bash, list which of errexit, nounset, pipefail and xtrace are on in your interactive shell.

Related commands

bash: exit codesExit codes, $?, set -euo pipefail and trapunsetRemove variables and functions from the shellenvShow the environment, or run a command with a changed onesourceRun a file's commands in the current shell
PreviousechoNextunset