LinuxQuestions.org
Visit the LQ Articles and Editorials section
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 04-01-2012, 11:36 PM   #1
khandu
Member
 
Registered: Sep 2003
Posts: 79

Rep: Reputation: 0
Question Bash Shell program question - if error then mailx


Hey Guys

Multiple questions

Basically I am trying to write a shell script in bash which does the following

1) Does some export and zip -- this part is easy and done
2) create a folder if it does not exist
3) Move files to that folder in (2)
4) if an error happens in step (1-3) then send a mail (mailx)

Now

What I have figured is

Code:
start if loop
start for loop for number of files
  do
    export files
  done;
mkdir -p /location/to/store/file
mv *.files /location/to/store/file
echo "Didn't work" | mailx -s Error on `hostname` email@me.com
fi
Now this will email everytime even if there is or isin't an error..

How do i do some kind of error trapping here that if

1) export file OR mkdir OR mv fails (or any return other than 0 from what i understand)

then the echo mailx gets kicked off

Ta
 
Old 04-02-2012, 03:19 AM   #2
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2374Reputation: 2374Reputation: 2374Reputation: 2374Reputation: 2374Reputation: 2374Reputation: 2374Reputation: 2374Reputation: 2374Reputation: 2374Reputation: 2374
Hi,

$? tells you if a command succeeded or failed. If the output is 0 (zero), the command ran the way it should have, anything else points to a failure. Using $? only works when used immediately after the command you need to check. Have a look at this:
Code:
ls foobar
if [[ "$?" != "0" ]] # is $? anything but 0
then
  echo "oeps..."     # your code goes here...
  exit 1             # stop the script
fi
The exit 1 makes sure your script stops running once it encounters an error.

If you need to check the success of a command multiple times you can either use the above code multiple times or make a function:
Code:
function errorHandler ()
{
  echo "oeps..."     # your code goes here...
  exit 1             # stop the script
}

ls foobar
[[ "$?" != "0" ]] &&  errorHandler  # is $? anything but 0

mv FooBar /x/y/z
[[ "$?" != "0" ]] &&  errorHandler  # is $? anything but 0
Hope this helps.
 
1 members found this post helpful.
Old 04-02-2012, 05:53 AM   #3
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947
You can also use any command directly in an if construct, not just the "["-type tests. The exit code is what if is checking for, after all.

Code:
if maincommand ; do
	<subcommands upon success (exit code =0)>
else
	<subcommands upon failure (exit code >0)>
fi
 
Old 04-02-2012, 06:11 AM   #4
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942
I fully agree with Druuna.

Since the exit status value ($?) itself does not matter -- we are only interested if it was nonzero --, I prefer to use a bit different form of a shell function (Fatal) for this:
Code:
FatalRecipient='my-address@example.com'
FatalSubject='This thing just failed, see'

function Fatal () {
    if [ $? -ne 0 ]; then
        echo -e "$@" | mailx -s "$FatalSubject" "$FatalRecipient"
        exit 1
    fi
    return 0
}
The idea is that you append || Fatal 'Description' after each command that should not fail. If, and only if, the left side of the || fails, the Description is e-mailed to $FatalRecipient using subject $FatalSubject :
Code:
cp -pf oldfile newfile || Fatal "Cannot copy 'oldfile' to 'newfile'."
If you want to fail unconditionally, use
Code:
false || Fatal 'Description'
since false will do nothing but fail; it does nothing but return a nonzero exit status.

Here is a real world example:

A typical operation in a script like this is to create a temporary working directory. This is how to do it so that it will be automatically deleted when the script exits, no matter why the script exits. If the temporary directory cannot be created, the script is aborted, and an error e-mail sent:
Code:
tempdir="$(mktemp -d)" || Fatal 'Cannot create a temporary directory.'

trap "rm -rf '$tempdir'" EXIT
The trap command removes the directory whenever the interpreter exits. (Because the command is in double quotes, the value of $tempdir is evaluated right then and there, when the trap is set. This means that even if you change tempdir later on, it will not affect the trap; regardless of the value of $tempdir when the script exits, the trap will always remove the original directory.)

Let us expand this example a bit further.

Let us say you wish to apply a sed operation to say all files in and under /var/lib/mystuff/. The following form requires Bash (read -rd ""), but does support all possible file names, even those containing whitespace or newlines or other weird characters:
Code:
LANG=C
LC_ALL=C

find /var/lib/mystuff/ -type f -print0 | while read -rd "" FILE ; do

    cp -f --preserve=all "$FILE" "$tempdir/copy" || Fatal "Could not backup '$FILE'."

    sed -e 's|something|other|g' "$FILE" > "$tempdir/copy" || Fatal "Could not edit '$FILE' using sed."

    mv -f "$tempdir/copy" "$FILE" || Fatal "Could not replace '$FILE'."

done
The LANG and LC_ALL are used to set the POSIX aka C locale, just in case you happen to have filenames with non-UTF-8 byte sequences in them. If you use an UTF-8 locale (and most of us do), the tools will abort if they encounter a non-UTF-8 byte sequence in a file name or other string. Setting the locale to POSIX tells tools to treat all names and strings as eight-bit byte sequences.

Note that this affects the sed , too. In the POSIX locale, does not match [a-z]. In the en_US.UTF-8 locale (and all other UTF-8 locales), it does! If you need or want that behaviour, you can always just add LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_CTYPE=en_US.UTF-8 before the sed command, on the same line, to change the locale only for the sed command.

The loop body will first copy the original file into the temporary directory, preserving all metadata (from ownership and mode, up to extended attributes). Ownership is only preserved if the user running the command is allowed to. This copy is done not to save the data, but to save the metadata; this happens to be the easiest way to copy all metadata.

The sed command overwrites the contents of the temporary copy. If it fails, the original file will be intact. Redirecting to the file does not change its metadata (other than size and modification timestamp).

Finally, the original file is replaced with the edited copy. If $tempdir is on the same filesystem, this is guaranteed to leave you with either the original file, or the new file, but never a broken copy. (For different filesystems, it depends on mv implementation; I believe Coreutils mv has the same guarantee across filesystems if using ext2/ext3/ext4/xfs/reiserfs.)

While the above sequence may look a bit cumbersome, it practically guarantees it will always Do The Right Thing. If it fails, the original file is kept intact. If it succeeds, only the contents of the file are changed (although actually the entire file is replaced). For example, SELinux security context, POSIX ACLs, and all extended attributes the file might have, should stay intact.

Moreover, if it fails for any reason, you will always get an e-mail message describing the reason. You could even add
Code:
        logger -p 'local.error' -i -t 'MyScript' "$@"
just before the exit 1 in the Fatal function body, to log the error message in the system log, in addition to sending an e-mail. See man logger for details on its use.

Hope this helps,
 
1 members found this post helpful.
Old 04-20-2012, 06:55 PM   #5
Dafydd
Member
 
Registered: Oct 2008
Posts: 305

Rep: Reputation: 23
While I was not part of this discussion, let me say that this is exactly the information I was seeking and answered my would be question completely.

LinuxQuestions comes through again.
Thank you guys.
Dave

I needed tobe sure the script was killed should an error for any reason pop up.
Code:
#!/bin/bash
##
# check if there is no command line argument
if [ $# -eq 0 ]
then
echo "You forgot the information: Month Year seperated by a space."
exit
fi

function errorHandler ()
{
  echo ".....process failed."     # your code goes here...
  exit 1             # stop the script
}

MONTH=$1;
YEAR=$2;

	cd work 
		[[ "$?" != "0" ]] &&  errorHandler;
	cp /media/VOLUMELABE/DCIM/101EKAIO/*.jpg . 
		[[ "$?" != "0" ]] &&  errorHandler;
	convert *.jpg -adjoin $MONTH-$YEAR.pdf  
		[[ "$?" != "0" ]] &&  errorHandler;
	cp $MONTH-$YEAR.pdf ../$YEAR 
		[[ "$?" != "0" ]] &&  errorHandler;
	rm *.jpg *.pdf
		[[ "$?" != "0" ]] &&  errorHandler;
	rm /media/VOLUMELABE/DCIM/101EKAIO/*.jpg 
		[[ "$?" != "0" ]] &&  errorHandler;

exit
 
  


Reply

Tags
bash, error, mailx, shell, trap


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
bash + mailx question Efo Linux - General 2 11-27-2011 11:17 AM
bash shell program question rsatyandra Programming 10 07-24-2011 09:15 AM
Using Bash shell when I run a program from it jimmyrp Linux - Newbie 6 05-15-2011 12:54 PM
Simple Bash Shell Program frankblack Programming 2 02-14-2003 11:59 PM
bash shell program help embsupafly Programming 7 11-27-2002 12:05 AM


All times are GMT -5. The time now is 10:59 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration