20

I am using set -e to stop execution of a script on first error.

The problem is that this does not tell me what went wrong.

How can update a bash script so it will display me the last command that failed?

2
  • 2
    Don't use set -e, use your own error checking. Commented May 24, 2012 at 18:25
  • 2
    I agree with Jordan. Please see BashFAQ/105 for more information. Commented May 25, 2012 at 1:29

5 Answers 5

22

Instead of set -e, use an ERR trap; you can pass $BASH_LINENO in to get the specific line number on which the error occurred. I provide a script taking advantage of this in my answer at https://stackoverflow.com/a/185900/14122

To summarize:

error() {
   local sourcefile=$1
   local lineno=$2
   # ...logic for reporting an error at line $lineno
   #    of file $sourcefile goes here...
}
trap 'error "${BASH_SOURCE}" "${LINENO}"' ERR
Sign up to request clarification or add additional context in comments.

4 Comments

You can also use both set -e and the ERR trap together, if you want your script to exit after calling the trap function, or you can call exit explicitly in the trap function when you want that to happen.
any idea how to make it handle unbound variables set -u;echo $str ?
Works great in our works bash library! No more digging to see what command failed.
Very nice! In case you wanted to use this mechanism here and there in your scripts without using a shared lib with this error function, I'd recommend to just add this line (while #!/bin/bash -e or set -e is on): trap 'echo "[ERROR] Error occurred at $BASH_SOURCE:$LINENO command: $BASH_COMMAND"' ERR .. This would also print the command that caused the failure.
5
  1. make err.sh

    set -e
    trap 'echo "ERROR: $BASH_SOURCE:$LINENO $BASH_COMMAND" >&2' ERR
    
  2. include it (. err.sh) in all your scripts.

  3. replace any

    ... | while read X ; do ... ; done

    with

    while read X ; do ... ; done < <( ... )

    in your scripts for the trap to give the correct line number/command in the error message

Comments

1

Have you tried with --verbose?

bash --verbose script.sh

Comments

1

You can't use set -e by itself because processing will immediately stop after any error. Take a look at the Set Builtin section of the Bash Reference Manual for more information about the -x and -v options, which you can use for debugging.

Something like:

set -e
set -v

will exit on any error, while showing you each input line as it is read. It will not, however, show you just the line with the error. For that, you will need to do your own explicit error checking.

For example:

set +e
if false; then
    real_exit_status=$?
    echo 'Some useful error message.' >&2
    exit $real_exit_status
fi

Comments

0

set -ex will show (all) lines as they are executed and stop at the first command returning nonzero (not as part of if/while/until constructs).

Comments

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.