Want to trap script error and return line number of failure

Hey all UNIX nerds- I've built a shell script which runs pretty well- only I want it to have much better error trapping. (Like the kind I could apply to every shell script I write).
I'm not a UNIX genius, and could really use a bit of help.

The original script goes something like this:

1  #VARIABLES
2 
3  export EMAIL_ADDRESS=somebody@somewhere.com
4  export LOG_DIR_NAME=backup_logs
5  #--------------------------------------------------------------------
6  #FUNCTIONS
7 
8  check_err()
9  {
10 LINE_NUMBER=$2
11 MESSAGE="Script failed at line number $LINE_NUMBER on "`date +"%m_%d_%y_%R:%S"`". Please check the logs located at "`pwd`"/$LOG_DIR_NAME/ for more details."
12 SUBJECT="FAILED BACKUP ON $HOSTNAME at Line $LINE_NUMBER"
13 if [ $1 -ne 0 ]; then
14 echo "$MESSAGE"| mailx -s "$SUBJECT" "$EMAIL_ADDRESS"
15 exit 1
16 fi
17 }
18 #--------------------------------------------------------------------
19 #Begin Script
20 
21  ...command1
22      check_err $? $LINENO #If it fails here, it will tell you it failed at line 22
23  ...command2
24      check_err $? $LINENO #If it fails here, it will tell you it failed at line 24
25  ...command3
26  ...command4
27      check_err $? $LINENO #If it fails here, it will tell you it failed at line 27
28 
29 #End Script

Note that this script sets a bunch of required variables first, then creates a function named check_err which will e-mail me if there's ever a problem with the script.
Note that the check_err function accepts two input parameters: the error number and the line number where the failure occurred.
...So far, pretty darn good.
But I don't want to have to call the check_err function (with the parameters error number and line number) after every command in the script.
And you can also see the limitations of the above method: If the e-mail says it failed at line 27, did it actually fail at line 24, or line 25? ...Its just saying that it failed at line 27 because that's the line the check_err function got run from.

What I probably want to do is have it execute in some kind of loop, and then, if there is an error, pass the error number and the EXACT line number to the check_err function to tell me EXACTLY where it failed, and why- and then exit.
I also don't want it to run the script in a loop forever, so there would have to be some kind of break condition...

You'll note I attempted something like this- which mostly works, except the downside is that the line number where it failed is never going to be accurate:

1  #VARIABLES
2 
3  export EMAIL_ADDRESS=somebody@somewhere.com
4  export LOG_DIR_NAME=backup_logs
5  #--------------------------------------------------------------------
6  #FUNCTIONS
7 
8  check_err()
9  {
10 LINE_NUMBER=$2
11 MESSAGE="Script failed at line number $LINE_NUMBER on "`date +"%m_%d_%y_%R:%S"`". Please check the logs located at "`pwd`"/$LOG_DIR_NAME/ for more details."
12 SUBJECT="FAILED BACKUP ON $HOSTNAME at Line $LINE_NUMBER"
13 if [ $1 -ne 0 ]; then
14 echo "$MESSAGE"| mailx -s "$SUBJECT" "$EMAIL_ADDRESS"
15 exit 1
16 fi
17 }
18 #--------------------------------------------------------------------
19 #Begin Script
20 
21 TIMES_AROUND=0
22 
23 while check_err $? $LINENO #With this code, whenever there is a failure, it will always tell you that it failed at line 23. ...Not really what we want.
24 do
25   TIMES_AROUND=`expr $TIMES_AROUND + 1`
26     if [ $TIMES_AROUND -lt 2 ]; then
27         echo "Hello This is the normal script run."
28         echo "The current iteration of this run is: "$TIMES_AROUND
29         FAIL! #Test hypothetical failure condition. The script will fail here, and send me an e-mail, then exit- which is *exactly* what we want- only, the line number at which it failed won't be 29- it will be line 23, where the "while check_err $? $LINENO" syntax is.
30     else
31         break
32    fi
33 done
34 
35 #End Script

I looked here and on Google, but could find nothing. Any help would be most appreciated.

Thanks!

Try set -x and just write everything to a log

#!/bin/ksh
set -x
exec 2>&1 > mylogfile
..........  code here

As to email, just be sure your script returns non-zero when it fails

myscript.sh parm1 || /usr/bin/uuencode mylogfile mylogfile |/usr/bin/mailx -s 'script failed' me@mycompany.com

Jim- I see what you're saying, but I really want to get the line number where it failed, and also (if possible) make it uncomplicated to call the script.

Doing it this way should make debugging and using the script a breeze.

...This is a script that will end up on several servers, so having it be correct, and having it easy to call is really what I'm looking for.

It would be better to call the check_err function only when you fail, something like this: -

some command || check_err $? $LINENO "msg"

In fact I use this syntax without the line number or exit code, just put what I want in the error msg, that way the error handler is generic. Mine is usually called tidyupexit and will handle cleaning up my temp files etc before exiting as well as giving the error message. If each error message is unique then you do not need the line number, just grep for the message in the offending script and it takes you to the heart of the problem.