Three shell settings stop a script on a failure you did not check yourself. They go on the script's second line: set -euo pipefail.
set -e ends the script at the first failed command, and the script's status is that command's status. A failure inside a condition — after if, to the left of && or || — does not stop the script: you check that status yourself. So only an explicit check prints FAIL: with set -e alone, a script with curl to an app that is down quietly ends with status 7.
set -u makes it an error to use a variable that does not exist. A typo, $URl instead of $URL, gives an empty string without this setting; with it, you get the message URl: unbound variable and the script stops.
A pipeline's status is the status of its last command. In curl -sf … | tee -a health.log, that is tee's status: it wrote empty output and succeeded even though curl failed. With set -o pipefail, the pipeline's status is that of the last command in it that failed.
There is no app.log file in the directory. What will ./report.sh print?
#!/bin/bash
set -e
grep ERROR app.log | wc -l
echo "report done"
-
A pipeline's status is that of its last command, wc: it counted zero lines and succeeded. Only
set -o pipefailstops the script. -
grep writes
No such file or directoryto the error stream, past the pipeline, so the message is on the screen as well.
grep failed, but the pipeline's status came from wc — zero — so set -e did not stop the script. set -o pipefail makes grep's failure the pipeline's status.
Key points
-
set -estops a script at the first unchecked failure; a failure afterifor to the left of&&and||does not stop it. -
set -uturns a typo in a variable name into an error instead of an empty string. -
With
pipefail, a failure early in a pipeline does not hide behind the success of its last command.