How to catch and handle nonzero exit status within a Bash function?
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
}
Related videos on Youtube
smitelli
Greetings! My name is Scott, I reside in the Raleigh-Durham, North Carolina area, and I do a little bit of everything. I’m a web developer professionally, and a sound mixer/editor in my spare time. I also have a wide range of other hobbies — from writing to time-lapse and still photography to drawing a webcomic.
Updated on September 18, 2022Comments
-
smitelli over 1 year
Say I have the following (pointless) Bash function:
myfunc() { ls failfailfail uptime }
I run it as follows:
myfunc || echo "Something is wrong."
What I want to happen is
ls
runs (as it should),failfailfail
does not work (since it doesn't exist), anduptime
doesn't run. The return value of the function would be nonzero, and the error message would be shown. The return value doesn't have to be the exact exit status of the failed command, it just shouldn't be zero.What actually happens is I get the output of
ls
, followed by "-bash: failfailfail: command not found", followed by the output ofuptime
. The error message is not shown, because the failed exit status is getting eaten.set -e
has no useful effect, either within the function or in the scope where the function is called. The only way I can get this to work the way I want is:myfunc() { ls || return $? failfailfail || return $? uptime || return $? }
But this seems awfully repetitive and ugly. Is there another way to clean this up?
-
Wildcard about 8 yearsYou can put line breaks after
&&
, which would make this easier to maintain IMO. You don't need backslashes for that, either. -
Julie Pelletier about 8 yearsIt's interesting but I think it may cause more confusion that way.
-
smitelli about 8 yearsThis feels... devious.
-
MAChitgarha over 4 yearsInstead of posting a new answer, you should edit the existing one. Your answer doesn't need to be a separate answer from the previous one.
-
Wildcard over 4 years@MAChitgarha this is from three years ago.
-
MAChitgarha over 4 years@Wildcard I know, but some people may search for a solution, now. Editing the previous answer is more helpful than adding an answer, though.