
Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
Aborting a Shell Script on Command Failure
Overview
By utilizing Bash scripts, we can have access to a powerful programming language. Writing such scripts is an efficient way to run several commands one after the other. Even if one command fails, the others will still be executed.
We'll learn how we can add some safeguards so that these errors don't happen. The example code has been tested in Bash. They should also work for other POSIX-compatible shell environments.
The Problem
Let's first take a look at how Bash handles error messages by default. Let's say we have a simple shell script called "hello.sh" which prints out the word "Hello" followed by the word "World".
#!/bin/bash echo hello echo world
Running it gives the expected result ?
$ ./hello.sh hello world
Next, we'll add a statement that?s guaranteed to fail.
#!/bin/bash echo hello cat non-existing-file echo world
If executed, this script will produce an output. Execution doesn't stop, but "world" is still outputted ?
$ ./hello.sh hello cat: non-existing-file: No such file or directory world
We also got a 0 exit code for our script which indicates everything went well.
$ echo $? 0
Exit on First Error
If you want to make a shell script exit whenever any command within the script fails, you can use the set -e option. This option tells the shell to exit immediately if any command within the script exits with a non-zero status.
Here's an example of how you can use the set -e option in a shell script ?
#!/bin/bash # Set the -e option set -e # Run some commands echo "Running command 1" command1 echo "Running command 2" command2 echo "Running command 3" command3 # The script will exit if any of the commands above fail echo "All commands completed successfully"
In this example, if any of the commands command1, command2, or command3 fail (i.e., exit with a non-zero status), the script will exit immediately and the remaining commands will not be executed.
Note that the set -e option only applies to commands that are run directly by the shell (e.g., echo, command1, etc.), not commands that are run as a result of a shell expansion (e.g., $(command)). To make the set -e option apply to all commands, including those run as a result of a shell expansion, you can use the set -o pipefail option in combination with set -e.
Using Pipefail
Unfortunately, this solution won't help if your script contains piped statements. For example, if we pipe the first two commands (the ones that fail) together, starting with the one that failed, then we get an error message.
#!/bin/bash set -e cat non-existing-file | echo hello echo world
Even though we use set -e, the following command outputs ?
$ ./hello.sh hello cat: non-existing-file: No such file or directory world
If we want to run multiple commands without failing if any one fails, let's add -o pipefail to the first command.
#!/bin/bash set -eo pipefail cat non-existing-file | echo hello echo world
We're telling bash that if an error happens inside a pipeline, it should stop and report the exit code of the last command in the pipeline.
$ ./hello.sh hello cat: non-existing-file: No such file or directory
This results in the same non-zero return code we've seen before ?
$ echo $? 1
Conclusion
We've learned how to use the command "exit" to make shell script terminate immediately when an error occurs. We also added -o pipefail so that pipes would behave in the same way as they did before. Always add set -eo pipeline fail at the beginning of your shell script.