LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - General
User Name
Password
Linux - General This Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.

Notices


Reply
  Search this Thread
Old 01-01-2009, 10:27 AM   #1
Diggy
Member
 
Registered: Jan 2009
Posts: 47

Rep: Reputation: 17
Script help


Hello, and Happy New Year, to all.

I've created a bash script to back up certain critical directories using rsync. It works fine, for the most part, but I have encountered a couple of problems:

1) I want the script to test for the presence of the backup destination directories. If they exist already, then send emails to that effect and exit. However, I'm not sure how to test for the separate directories before exiting (hope that's clear). Here's my code snippet:

# Create backup directories. If they already exist then exit.
#
if [ -d $DESTDIR/$DATE ] ; then
echo "$DESTDIR/$DATE already exists, so backup must already be done" \
|mailx -s "Backup Summary `date +"%m/%d/%y %r"`" $EMAIL
exit
elif [ ! -d $DESTDIR/$DATE ] ; then
mkdir $DESTDIR/$DATE
fi

if [ -d $DESTDIR2/$DATE ] ; then
echo "$DESTDIR2/$DATE already exists, so backup must already be done" \
|mailx -s "Backup Summary `date +"%m/%d/%y %r"`" $EMAIL
exit
elif [ ! -d $DESTDIR2/$DATE ] ; then
mkdir $DESTDIR2/$DATE
fi

As you can see, if the first argument is true, the second is never tested because we've already exited. How can I make the script test for both, and send (an) email(s) before exiting?

2) I want directories older than 14 days to be deleted. The script works if I run it manually, but not if run from cron. Here's the code snippet:

if [ -d $DESTDIR ]; then
find $DESTDIR -maxdepth 1 -mtime +$DAYSOLD -exec rm -Rf {} \;
fi

if [ -d $DESTDIR2 ]; then
find $DESTDIR2 -maxdepth 1 -mtime +$DAYSOLD -exec rm -Rf {} \;
fi

I've seen posts to the effect that the full path must be used, rather than a variable, if the script is to work from cron. But, does anyone know of any way I can make this work using variables?

Many thanks for your help!

Diggy
 
Old 01-01-2009, 11:05 AM   #2
mesiol
Member
 
Registered: Nov 2008
Location: Lower Saxony, Germany
Distribution: CentOS, RHEL, Solaris 10, AIX, HP-UX
Posts: 731

Rep: Reputation: 137Reputation: 137
Hi,

do not run your test in 2 statements, create one statement using logical AND (||) some like this:

if [ -f $DESTINATION1 ] || [ -f DESTINATION2 ];
then echo BACKUP_EXISTS;
exit 1;
else
echo NO_BACKUP_DO_SOMETHING;
fi

This will prevent you from exiting during your first test before second test is done.

There is also a logical OR (&&)

Hope i could help.
 
Old 01-01-2009, 11:16 AM   #3
Diggy
Member
 
Registered: Jan 2009
Posts: 47

Original Poster
Rep: Reputation: 17
Thanks so much! That makes sense. But, as I think more about it, I realize that my logic is flawed. If one backup destination directory exists, but the other doesn't, then my script should ignore any further commands having to do with existing directory, but continue with commands for the non-existing one. Can I build upon what you've suggested to accomplish that?

Diggy
 
Old 01-02-2009, 07:31 AM   #4
openSauce
Member
 
Registered: Oct 2007
Distribution: Fedora, openSUSE
Posts: 252

Rep: Reputation: 39
Quote:
Originally Posted by Diggy View Post
Thanks so much! That makes sense. But, as I think more about it, I realize that my logic is flawed. If one backup destination directory exists, but the other doesn't, then my script should ignore any further commands having to do with existing directory, but continue with commands for the non-existing one. Can I build upon what you've suggested to accomplish that?

Diggy
Sure. Just remove the exit command from your if block. Also, a general point about if/else:

Code:
if [ sometest ]; then
  do something;
elif [ ! sometest ]; then
# there's no need to include the negation of your test in the
# line above.  we know 'sometest' returns false as we're
# already in the 'else' block. Just use 'else' instead of 'elif'
fi
Re your 2nd question, any script run from the shell should be runnable from cron. Are you failing to initialise your variables when you run the command from cron? How are they initialised in the script which you run manually?
 
Old 01-02-2009, 08:10 AM   #5
Diggy
Member
 
Registered: Jan 2009
Posts: 47

Original Poster
Rep: Reputation: 17
Thanks for your reply, openSauce.

If I remove the exit command from my if block, what happens if the directories are already created (thus indicating that the script/backup was already run)? I wouldn't want the backup to be done again. Hence the test.

As for initializing my variables, at the top of my delete directory script:

DESTDIR=/backup-external #where to back up to - destination
DESTDIR2=/public/nightly_backup #where to back up to - destination
DAYSOLD="13" #delete backup directories more than x+1 days old

Again, if I run the script manually, works a treat. But from cron, no joy.

Your continued help is very much appreciated.

Diggy
 
Old 01-02-2009, 08:38 AM   #6
openSauce
Member
 
Registered: Oct 2007
Distribution: Fedora, openSUSE
Posts: 252

Rep: Reputation: 39
Sorry, forgot to mention, your backup should be in the else block. So the general logic is

Code:
if [ backup already done ]; then
  send an email
else
  do backup
fi
"do backup" could be replaced by a function call if you know how to declare functions, to avoid duplicating code for the different directories. Or you can just copy/paste the backup code you already have.

=================================================

When you run from cron, are you calling exactly the same script which works if you run it manually, or are you just running
Code:
if [ -d $DESTDIR2 ]; then
find $DESTDIR2 -maxdepth 1 -mtime +$DAYSOLD -exec rm -Rf {} \;
fi
in your crontab?

If you are running the same script (as you should be), try redirecting std out and std err to a file and see what error messages you get. It could be a permissions issue, or perhaps the script is not in cron's $PATH?

Last edited by openSauce; 01-02-2009 at 08:41 AM. Reason: thinko
 
Old 01-02-2009, 08:40 AM   #7
openSauce
Member
 
Registered: Oct 2007
Distribution: Fedora, openSUSE
Posts: 252

Rep: Reputation: 39
PS: mesiol mixed up and and or. And is &&, or is ||.
 
Old 01-02-2009, 08:52 AM   #8
Diggy
Member
 
Registered: Jan 2009
Posts: 47

Original Poster
Rep: Reputation: 17
I wish I knew how to create a function, and to put the script in cron's path (the latter might be the solution to my problem. I'll have to RTFM :-) ). As a starter, and not to be lazy, might you share how to do these with me?

Many thanks.

Diggy
 
Old 01-02-2009, 08:52 AM   #9
i92guboj
Gentoo support team
 
Registered: May 2008
Location: Lucena, Córdoba (Spain)
Distribution: Gentoo
Posts: 4,083

Rep: Reputation: 405Reputation: 405Reputation: 405Reputation: 405Reputation: 405
Quote:
Originally Posted by mesiol View Post
Hi,

do not run your test in 2 statements, create one statement using logical AND (||) some like this:
openSauce already cleared that. That's OR, not AND. But besides that, I would use AND (the real one). Unless the OP really mean OR. This code that you posted will exit if one of the destinations exist.

Code:
if [ -f $DESTINATION1 ] ||  [ -f DESTINATION2 ]; 
        then echo BACKUP_EXISTS;
             exit 1;
So, if "$DESTINATION1" exist, "$DESTINATION2" is not even checked (which means it might not exist). So, you probably want to use &&, and not ||.

Also, the colons are not needed. They are redundant. You only need then when you want to concatenate two sentences on a single line. So, I'd either do:

Code:
if [ -f $DESTINATION1 ] ||  [ -f DESTINATION2 ]
  then echo BACKUP_EXISTS
  exit 1
or

Code:
if [ -f $DESTINATION1 ] ||  [ -f DESTINATION2 ]; then
  echo BACKUP_EXISTS
  exit 1
But, in first place, I think that the first idea was maybe better. You want to check separately both things, and not concatenate them. Why? Because you might need to backup one destination, but not the other...

I also suggest declaring functions, for both the backup and the exit+send mail functionalities.

Last edited by i92guboj; 01-02-2009 at 08:54 AM.
 
Old 01-02-2009, 09:05 AM   #10
openSauce
Member
 
Registered: Oct 2007
Distribution: Fedora, openSUSE
Posts: 252

Rep: Reputation: 39
Quote:
Originally Posted by Diggy View Post
I wish I knew how to create a function, and to put the script in cron's path (the latter might be the solution to my problem. I'll have to RTFM :-) ). As a starter, and not to be lazy, might you share how to do these with me?

Many thanks.

Diggy
Declaring functions isn't essential for now, although it'll make your code easier to read, debug and maintain. I've seen this guide recommended several times as an intro to bash scripting (don't be put off by the "advanced" in the title! It starts with the basics).

For now, the relevant line in crontab should be something like this.
Code:
* * * * * /home/[your_user_name]/delete_dir_script.sh >/home/[your_user_name]/delete_dir_log 2>&1
Save the script you want to run in your home directory with the name delete_dir_script.sh. And replace at least some of the *'s with numbers, unless you want the script to run every minute! The part beginning with '>' redirects all the script's output to a file called delete_dir_log in your home directory, and 2>&1 redirects all error messages to the same file. Once the script is run, you can examine this file (and paste it here if you need to) to work out what the problem is.

cheers

OS
 
Old 01-02-2009, 09:12 AM   #11
Diggy
Member
 
Registered: Jan 2009
Posts: 47

Original Poster
Rep: Reputation: 17
I guess in need i need to do this:

If exists a and b, then email and exit.
If exists a but not b, then backup b, email, and exit.
If does not exist a but exists b, then backup a, email, and exit.
If does not exist a or b, then backup a and b, email, and exit.

Just not sure how to code that.

Diggy
 
Old 01-02-2009, 09:31 AM   #12
i92guboj
Gentoo support team
 
Registered: May 2008
Location: Lucena, Córdoba (Spain)
Distribution: Gentoo
Posts: 4,083

Rep: Reputation: 405Reputation: 405Reputation: 405Reputation: 405Reputation: 405
Quote:
Originally Posted by Diggy View Post
I guess in need i need to do this:

If exists a and b, then email and exit.
If exists a but not b, then backup b, email, and exit.
If does not exist a but exists b, then backup a, email, and exit.
If does not exist a or b, then backup a and b, email, and exit.

Just not sure how to code that.

Diggy
The simplest way is your original idea, without the exits. I've used some cleaning and made a function just for the sake of doing an example.

Code:
function foo() {
  echo "$1 already exist, so backup must already be done." | \
    mailx -s "Backup Summary `date +"%m/%d/%y %r"`" $EMAIL
}

if [ -d "$DESTDIR/$DATE" ]; then
  foo "$DESTDIR/$DATE"
else
  mkdir "$DESTDIR/$DATE"
fi

if [ -d "$DESTDIR2/$DATE" ]; then
  foo "$DESTDIR/$DATE"
else
  mkdir "$DESTDIR2/$DATE"
fi
This way, the ifs do not interfere with each other, which is what you intend.
 
Old 01-02-2009, 09:44 AM   #13
Diggy
Member
 
Registered: Jan 2009
Posts: 47

Original Poster
Rep: Reputation: 17
i92guboj,

Ah, suberb. But, does the function keep either backup (or both backups) from happening if they're already complete (and by complete, my script simply checks for the existence of the destination directories)?

Diggy


PS - Thanks, openSauce. I'll send script output to a file, as you suggest, and report results (can't run script until tonight, though).
 
Old 01-02-2009, 10:05 AM   #14
i92guboj
Gentoo support team
 
Registered: May 2008
Location: Lucena, Córdoba (Spain)
Distribution: Gentoo
Posts: 4,083

Rep: Reputation: 405Reputation: 405Reputation: 405Reputation: 405Reputation: 405
Quote:
Originally Posted by Diggy View Post
i92guboj,

Ah, suberb. But, does the function keep either backup (or both backups) from happening if they're already complete (and by complete, my script simply checks for the existence of the destination directories)?

Diggy


PS - Thanks, openSauce. I'll send script output to a file, as you suggest, and report results (can't run script until tonight, though).
The checks are the same you did on your first post. Read the code carefully, and you will understand it. If the check is sucessful (dir exist), the foo function is called (and it sends the mail), if not, the mkdir is called. It's exactly the same thing you were doing on the first post. Except that I don't call exit.

The checks are still done out of the function, on the if-then-else blocks.
 
Old 01-02-2009, 10:24 AM   #15
Diggy
Member
 
Registered: Jan 2009
Posts: 47

Original Poster
Rep: Reputation: 17
Sorry, I should have included the entire script for clarity. Here's the remainder:

# Backup source directories to destination directories
for d in $LIST; do
rsync -az $SRCDIR/$d/ $DESTDIR/$DATE/$d
rsync -az $SRCDIR/$d/ $DESTDIR2/$DATE/$d \
|mail -s "Backup Summary `date +"%m/%d/%y %r"`" $EMAIL
done

# Email results of backup
if [ $? -eq 0 ]; then
mail -s "Backup: SUCCESS" $EMAIL << EOF
Your backup from $SRCDIR to $DESTDIR completed successfully.
EOF
else
mail -s "Backup: FAILURE" $EMAIL << EOF
Your backup from $SRCDIR to $DESTDIR did not complete.
EOF
fi

exit

Sorry to be so dense, but will the function keep the above from running if the destination directory or directories already exist. It doesn't appears so to me.

Diggy
 
  


Reply



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 On
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
I want to run script on the server from client machine in windows in a perl script vpradeep Linux - Newbie 2 09-01-2008 03:29 AM
set variables in a bash script; ansi PS1 color script donnied Programming 4 11-21-2007 11:33 AM
Iptables (with masq) troubleshooting, very simple script attached script and logs. xinu Linux - Networking 13 11-01-2007 04:19 AM
Shell Script: want to insert values in database when update script runs ring Programming 2 10-25-2007 10:48 PM
send automatic input to a script called by another script in bash programming jorgecab Programming 2 04-01-2004 12:20 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - General

All times are GMT -5. The time now is 08:33 AM.

Main Menu
Advertisement
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
Open Source Consulting | Domain Registration