Bash – How to make bash abort the execution of a script on syntax error

basherror handlingshell-script

To be on safe side, I'd like bash abort the execution of a script if it encounters a syntax error.

To my surprise, I can't achieve this. (set -e is not enough.) Example:

#!/bin/bash

# Do exit on any error:
set -e

readonly a=(1 2)

# A syntax error is here:

if (( "${a[#]}" == 2 )); then
    echo ok
else
    echo not ok
fi

echo status $?

echo 'Bad: has not aborted execution on syntax error!'

Result (bash-3.2.39 or bash-3.2.51):

$ ./sh-on-syntax-err
./sh-on-syntax-err: line 10: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$ 

Well, we can't check $? after every statement to catch syntax errors.

(I expected such safe behavior from a sensible programming language… perhaps this must be reported as a bug/wish to bash developers)

More experiments

if makes no difference.

Removing if:

#!/bin/bash

set -e # exit on any error
readonly a=(1 2)
# A syntax error is here:
(( "${a[#]}" == 2 ))
echo status $?
echo 'Bad: has not aborted execution on syntax error!'

Result:

$ ./sh-on-syntax-err 
./sh-on-syntax-err: line 6: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$ 

Perhaps, it's related to exercise 2 from http://mywiki.wooledge.org/BashFAQ/105 and has something to do with (( )). But I find it still unreasonable to continue executing afte a syntax error.

No, (( )) makes no difference!

It behaves bad even without the arithmetic test! Just a simple, basic script:

#!/bin/bash

set -e # exit on any error
readonly a=(1 2)
# A syntax error is here:
echo "${a[#]}"
echo status $?
echo 'Bad: has not aborted execution on syntax error!'

Result:

$ ./sh-on-syntax-err 
./sh-on-syntax-err: line 6: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$ 

Best Answer

Wrapping the whole into a function seems to do the trick:

#!/bin/bash -e

main () {
readonly a=(1 2)
    # A syntax error is here:
    if (( "${a[#]}" == 2 )); then
        echo ok
    else
        echo not ok
    fi
    echo status $?
    echo 'Bad: has not aborted execution on syntax error!'
}

main "$@"

Result:

$ ./sh-on-syntax-err 
$ ./sh-on-syntax-err line 6: #: syntax error: operand expected (error token is "#")
$ 

Though I have no clue why - maybe someone else can explain?

Related Question