How to handle errors reliably in a shell function called as a condition?
Using bash 4.1.5:
#!/bin/bash
set -e
foo()
{
false
echo "argh, I don't want to get there! What about set -e?!"
}
foo && echo "ok"
This yields the following output:
argh, I don't want to get there! What about set -e?!
ok
This issue occurs whenever foo
is called as a condition (i.e inside if
, while
, &&
, ||
, etc.). foo
behaves correctly if called as a simple command.
I find this behavior surprising and quite frankly dangerous, because this means that the behavior of a bash funct开发者_Go百科ion changes depending on how it is called. For example, even something as simple as foo
and foo && true
will not yield the same results. This is very troubling! One can only imagine how much chaos this could cause if foo
is doing sensitive operations...
Is there any workaround I could use to avoid this kind of situation?
Why don't you make foo() return a non-zero exit code if it fails?
foo(){
return 1
echo "argh, I don't want to get here! What about set -e?!"
}
The behavior you describe is expected, and quite necessary. Consider a function like:
word_is_in_file() { grep $1 $2 > /dev/null }
Now, consider a script that uses this function (sorry, this example is a bit contrived since a real script would probably just invoke grep directly) to make a decision:
if word_is_in_file $word $file; then do_something else do_something_else fi
The definition of the function may be buried in a library of shell functions that the author never sees. The author does not consider the grep failure to be a failure, and would be very baffled if the script terminated because of it.
A way to get the semantics you desire is to do something like:
foo() { # This function will abort if errors are encountered, but # the script will continue sh -e -c ' false echo not reached' } foo && echo not reached echo reached foo echo not reached
The semantics of set -e are also set to not abort the script in the "foo && ..." case for the same reason. It allows branching.
精彩评论