2

I want that my BASH script exits on errors in the script. But I don't get it working.

I tried both ways, using trap and set -e, and also both at the same time.

Here is a test script:

#!/bin/bash

# Exit on error
trap 'exit' ERR
set -e

h=1
b=$((h+)) # this produces an error
echo $?
echo $b
echo "end"

And the output looks like if I run the script:

test.sh: line 8: h+: syntax error: operand expected (error token is "+")
1

end

Why is it not working, and how do I get each of the two ways working?

13
  • What's the point of this? the ERR trap and set -e are not here for syntax errors. Commented Dec 29, 2016 at 11:17
  • @gniourf_gniourf: Wanted to know that myself, let me know if answer makes sense, because I can't find a proper reference for my solution below, to have a syntax error causing instruction and run in sub-shell or function is causing a proper EXIT signal Commented Dec 29, 2016 at 11:18
  • @Inian: I don't really know if it makes sense… what's the point of using a tool that's not designed for this job anyway? Commented Dec 29, 2016 at 11:20
  • @gniourf_gniourf: Well, this is not about syntax errors. I could have used in the example also $((h+j)), and if the variable j would be empty (e.g. due to some previous problems in the script, then the cause of error is the same as in my above example. Commented Dec 29, 2016 at 11:21
  • @Jadzia: no, this wouldn't have caused any issue. In arithmetic context, an unset (or set to the empty string) variable is considered as 0. (Unless you also use set -u, of course). Commented Dec 29, 2016 at 11:22

3 Answers 3

2

You are (willfully) introducing a syntax error in the context of set -e and a trap. You identify a behavior that seems unexpected regarding these. But I do not think the issue has to do with either the trap or the shell option.

Try this (not in your script, just in an interactive shell) :

echo $(( H+ )) && echo OK || echo NOT_OK

This will fail, of course (try echo $? right after). But it will not echo "NOT_OK", it will echo nothing at all, which does not seem natural at all.

Therefore, in the presence of a syntax error, the normal shell semantics break down. You cannot assume that failure by syntax error behaves like a command returning a non-zero status, it clearly bypasses some parts of the expected shell error-handling behavior we are used to.

One more thing... This is a syntax error in the arithmetic expression, but is not detected when the script is parsed. It does not prevent the script from being executed (contrary to missing quotes, brackets...).

This does the same thing :

[[ A = ]] && echo OK || echo NOT_OK

But this does not (will display NOT_OK) :

[ A = ] && echo OK || echo NOT_OK

Double-bracketed conditionals are reserved words, while single-bracketed conditionals are shell builtins, so that may have to do with the difference in behavior.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you very much for your answer, it quite clarifying! I think I understand your argument with the syntax error. So the bash script can be principally be syntax error free, but if for example some external input is used, which is not in the form as it should be, it can also lead to a syntax error. That's what has happened in my application.
I do not know if the actual shell source code would consider that a "syntax error " in the same sense as a non-matches parentheses, but it obviously fails in a way that is different from a command returning a non-zero code. Intuitively, I would say that instead of the command returning the error code, it could be the shell that decides there is a syntax error, stops executing the statement (all of it, bypassing what follows after || or &&), and then setting the return code itself, not using that of the $(( )) construct. But that is just a theory.
2

You should try to use #!/bin/sh instead of #!/bin/bash on the first line of your script. Else you can enable error trace in your bash set -o errtrace.

From bash man page:

the ERR trap is not inherited unless the -o errtrace shell option has been enabled.

4 Comments

Thank you for your answer. The second way seems to be very nice. But the first way with "#!/bin/sh" might be problematic since /bin/sh might be linked to another shell than bash, isn't it?
@Jadzia: With your original code, what change solved your problem, Can you edit the answer to demonstrate it?
@Inian: Actually I just assumed that it works so far, but didn't have tested it. I tested it in the now, and it does not seem to work actually. I placed the option "set -o errtrace" at the very top of the script.
I tried it, but it does not work. And even if it would, my interactive shell would quit as well if I cause an error by some type for example.
0

I guess you like to increment h ? then do b=$((h++))

1 Comment

Thanks for your answer. But no, I don't want to do increase h. This was just used as an example to create an error. The entire point here is about error handling.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.