Under set -e
, the non-existence of failfailfail
causes the whole script to exit (or the subshell, if the function is executed in a subshell).
If you don't need to modify the shell state from the function, you can run it in a subshell.
myfunc() (
set -e
ls
failfailfail
uptime
)
Another approach in bash is to set an ERR
trap to execute return
. If you want to make it a local setting, you need to restore the old trap value, which is a little cumbersome.
myfunc() {
local old_ERR_trap=$(trap -p ERR)
if [[ -z $old_ERR_trap ]]; then old_ERR_trap="trap - ERR"; fi
trap 'local ret=$?; eval "$old_ERR_trap"; return $ret' ERR
ls
failfailfail
uptime
}
One option would be to put the commands in a bash script, and start it with set -e
.
This will cause the script to terminate early if any command exits with non-zero exit status.
See also this question on stack overflow: https://stackoverflow.com/q/19622198/828193
To print the error, you could use
trap 'do_something' ERR
Where do_something
is a command you would create to show the error.
Here is an example of a script to see how it works:
#!/bin/bash
set -e
trap 'echo "******* FAILED *******" 1>&2' ERR
echo 'Command that succeeds' # this command works
ls non_existent_file # this should fail
echo 'Unreachable command' # and this is never called
# due to set -e
And this is the output:
$ ./test.sh
Command that succeeds
ls: cannot access 'non_existent_file': No such file or directory
******* FAILED *******
Also, as mentioned by @jick, keep in mind that the exit status of a pipeline is by default the exit status of the final command in it. This means that if a non-final command in the pipeline fails, that won't be caught by set -e
. To fix this problem if you are concerned with it, you can use set -o pipefail
As suggested my @glenn jackman and @Monty Harder, using a function as the handler can make the script more readable, since it avoids nested quoting. Since we are using a function anyway now, I removed set -e
entirely, and used exit 1
in the handler, which could also make it more readable for some:
#!/bin/bash
error_handler() {
echo "******* FAILED *******" 1>&2
exit 1
}
trap error_handler ERR
echo 'Command that succeeds' # this command works
ls non_existent_file # this should fail
echo 'Unreachable command' # and this is never called
# due to the exit in the handler
The output is identical as above, though the exit status of the script is different.
Best Answer
With help of Bash capture any error like -e but don't exit, do something else I found way to show error message before terminating script.
One may use
trap
to ensure that specified code is executed on encountering error, what happens immediately before-e
option terminates script. For examplewill result in