[ad_1]
By default, a Bash script on Linux will report an error but continue to run. We show you how to handle errors yourself so you can decide what should happen next.
Error handling in scripts
Error handling is part of programming. Even if you write flawless code, you can still run into error conditions. Your computer environment changes over time, as you install and uninstall software, create directories, and make upgrades and updates.
For example, a script that used to run without a problem can run into trouble if directory paths change or permissions on a file change. The default action of the Bash shell is to print an error message and continue executing the script. This is a dangerous default value.
If the action that failed is critical to some other processing or action that occurs later in your script, that critical action will not succeed. How disastrous that turns out depends on what the script is trying to do.
A more robust scheme would catch errors and allow the script to work if it needs to shut down or try to remedy the fault condition. For example, if a directory or file is missing, it may be satisfactory for the script to recreate it.
If the script has encountered a problem from which it cannot recover, it can be closed. If the script needs to exit, you may be given the opportunity to do any necessary cleanup, such as deleting temporary files or writing the error condition and exit reason to a log file.
Output state detection
Commands and programs generate a value that is sent to the operating system when they are finished. This is called your exit status. It has a value of zero if there were no errors, or some non-zero value if an error occurred.
We can check the exit status, also known as the return code, of the commands used by the script and determine if the command was successful or not.
In Bash, zero equals true. If the command response is not true, we know that a problem has occurred and we can take appropriate action.
Copy this script into an editor and save it to a file called “bad_command.sh”.
#!/bin/bash if ( ! bad_command ); then  echo "bad_command flagged an error."  exit 1 fi
You will need to make the script executable with the chmod
domain. This is a step that is required to make any script executable, so if you want to test the scripts on your own machine, remember to do this for each one. Substitute the appropriate script name in each case.
chmod +x bad_command.sh
When we run the script, we see the expected error message.
./bad_command.sh
There is no such command as “bad_command”, nor is it the name of a function within the script. It can’t be executed, so the answer is No zero. If the answer is not zero, the exclamation mark is used here as the logical answer. NOT
operator — the body of the if
the statement is executed.
In a real-world script, this might terminate the script, which our example does, or it might attempt to remedy the fault condition.
could look like the exit 1
the line is redundant. After all, there is nothing else in the script and it will terminate anyway. but using the exit
The command allows us to pass an exit status to the shell. If our script is ever called from a second script, that second script will know that this script encountered errors.
you can use logic OR
operator with the exit status of a command, and call another command or a function in your script if there is a non-zero response from the first command.
command_1 || command_2
This works because the first command executes OR
the second. The leftmost command is executed first. If it is successful, the second command is not executed. But if the first command fails, the second command is executed. So we can structure code like this. This is “logical-o./sh”.
#!/bin/bash error_handler() { Â echo "Error: ($?) $1" Â exit 1 } bad_command || error_handler "bad_command failed, Line: ${LINENO}"
We have defined a function called error_handler
. This prints the exit status of the failed command, contained in the variable $?
and a line of text that is passed to it when the function is called. This is done in the variable $1
. The function ends the script with an exit status of one.
The script tries to run bad_command
which obviously fails, so the command to the right of the logic OR
operator, ||
, is executed. This calls the error_handler
function and passes a string that names the command that failed and contains the line number of the command that failed.
We’ll run the script to see the error handler message, and then check the exit status of the script using echo.
./logical-or.sh
echo $?
our little error_handler
The function provides the exit status of the execution attempt. bad_command
, the command name, and the line number. This is useful information when you are debugging a script.
The exit status of the script is one. The exit status 127 reported by error_handler
means “command not found”. If we wanted, we could use that as the exit status of the script by passing it to exit
domain.
Another approach would be to extend error_handler
to check the different possible values ​​of the exit status and perform different actions accordingly, using this kind of construct:
exit_code=$? if [ $exit_code -eq 1 ]; then echo "Operation not permitted" elif [ $exit_code -eq 2 ]; then echo "Misuse of shell builtins" . . . elif [ $status -eq 128 ]; then echo "Invalid argument" fi
Use set to force an exit
If you know that you want your script to exit whenever there is an error, you can force it to do so. it means that you give up the possibility of any cleanup, or indeed any further damage, because your script terminates as soon as it detects an error.
To do this, use the set
command with the -e
(mistake) option. This tells the script to exit whenever a command fails or returns an exit code greater than zero. Also, using the -E
The option ensures that error detection and trapping work in shell functions.
To catch uninitialized variables as well, add the -u
(disarmed) option. To ensure that errors are caught in piped streams, add the -o pipefail
option. Without this, the exit status of a pipelined script is the exit status of the final command in the sequence. A failed command in the middle of the piped stream would not be detected. the -o pipefail
The option should come in the list of options.
The sequence to add to the top of your script is:
set -Eeuo pipefail
Here’s a short script called “unset-var.sh”, with an unset variable in it.
#!/bin/bash set -Eeou pipefail echo "$unset_variable" echo "Do we see this line?"
When we run the script, unset_variable is recognized as an uninitialized variable and the script ends.
./unset-var.sh
The second echo
the command is never executed.
Use error trap
The Bash trap command allows you to designate a command or function to be called when a particular signal is generated. Typically this is used to pick up signals like SIGINT
which is raised when you press the Ctrl + C key combination. This script is “sigint.sh”.
#!/bin/bash trap "echo -e 'nTerminated by Ctrl+c'; exit" SIGINT counter=0 while true do echo "Loop number:" $((++counter)) sleep 1 done
the trap
The command contains a echo
command and the exit
domain. It will activate when SIGINT
is high. The rest of the script is a simple loop. If you run the script and press Ctrl + C, you will see the message of the trap
definition, and the script will terminate.
./sigint.sh
we can use trap
with the ERR
signal to detect errors as they occur. These can then be fed into a command or function. This is “trap.sh”. We are sending error notifications to a function called error_handler
.
#!/bin/bash trap 'error_handler $? $LINENO' ERR error_handler() { echo "Error: ($1) occurred on $2" } main() { echo "Inside main() function" bad_command second third exit $? } second() { echo "After call to main()" echo "Inside second() function" } third() { echo "Inside third() function" } main
Most of the script is inside the main
function, which calls the second
Y third
functions When an error is encountered, in this case, because bad_command
does not exist – the trap
statement directs the error to the error_handler
function. Passes the failed command’s exit status and line number to the error_handler
function.
./trap.sh
Our error_handler
The function simply lists the details of the error in the terminal window. If you wanted, you could add a exit
command to the function so that the script ends. Or you could use a series of if/elif/fi
statements to perform different actions for different errors.
It might be possible to fix some errors, others might require the script to be stopped.
One final tip
Catching bugs often means getting ahead of things that can go wrong and putting in code to handle those eventualities should they arise. That’s in addition to making sure the execution flow and internal logic of your script are correct.
If you use this command to run your script, Bash will show you trace output as the script runs:
bash -x your-script.sh
Bash writes the output of the trace to the terminal window. He shows each command with its arguments, if any. This happens after the commands have been expanded, but before they are executed.
It can be of great help in tracking down elusive bugs.
RELATED: How to validate the syntax of a Linux Bash script before running it
[ad_2]