Take the 2-minute tour ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

I have this bash script and is run via cron on a regular interval:

#!/bin/bash

RSYNC=/usr/bin/rsync
SSH=/usr/bin/ssh
KEY=/Users/admin/Documents/Backup/rsync-key
RUSER=philosophy
RHOST=example.com
RPATH=data/
LPATH="/Volumes/G Technology G Speed eS/Backup"
LOCKFILE=/Users/admin/Documents/backup.isrunning

if [ ! -e $LOCKFILE ]; then
    touch $LOCKFILE
    $RSYNC -avz --delete --progress -e "$SSH -i $KEY" "$LPATH" $RUSER@$RHOST:$RPATH
    rm $LOCKFILE
else
    echo "Rsync - Backup still running"
fi

The backup could take any length of time, from a few minutes to days and if I run the backup via cron every 6 hours what I dont want is two instances of this running at the same time. So what I've done is created a simple locking mechanism. But I'm woried that if the script is killed half way through for what ever reason that lock file is always going to be there and the backup routine is not going to run.

Is there a way of enhancing this to be better fool proof?

Thanks

Scott

EDIT: Final bash script I'm now using thanks to the answer below:

#!/bin/bash

RSYNC=/usr/bin/rsync
SSH=/usr/bin/ssh
KEY=/Users/admin/Documents/Backup/rsync-key
RUSER=philosophy
RHOST=example.com
RPATH=data/
LOCKFILE=/Users/admin/Documents/Backup/backup.isrunning

if [ ! -e $LOCKFILE ]
then
    echo $$ >"$LOCKFILE"
else
    PID=$(cat "$LOCKFILE")
    if kill -0 "$PID" >&/dev/null
    then
        echo "Rsync - Backup still running"
        exit 0
    else
        echo $$ >"$LOCKFILE"
        echo "Warning: previous backup appears to have not finished correctly"
    fi
fi

LPATH="/Volumes/G Technology G Speed eS/Backup"
$RSYNC -avz --delete --progress -e "$SSH -i $KEY" "$LPATH" $RUSER@$RHOST:$RPATH

LPATH="/Volumes/G Technology G Speed eS/Catalogue"
$RSYNC -avz --delete --progress -e "$SSH -i $KEY" "$LPATH" $RUSER@$RHOST:$RPATH

LPATH="/Volumes/G Technology G Speed eS/Digital"
$RSYNC -avz --delete --progress -e "$SSH -i $KEY" "$LPATH" $RUSER@$RHOST:$RPATH

LPATH="/Volumes/G Technology G Speed eS/Finance"
$RSYNC -avz --delete --progress -e "$SSH -i $KEY" "$LPATH" $RUSER@$RHOST:$RPATH

LPATH="/Volumes/G Technology G Speed eS/Image Libraries"
$RSYNC -avz --delete --progress -e "$SSH -i $KEY" "$LPATH" $RUSER@$RHOST:$RPATH

LPATH="/Volumes/G Technology G Speed eS/IT Desk"
$RSYNC -avz --delete --progress -e "$SSH -i $KEY" "$LPATH" $RUSER@$RHOST:$RPATH

LPATH="/Volumes/G Technology G Speed eS/Office"
$RSYNC -avz --delete --progress -e "$SSH -i $KEY" "$LPATH" $RUSER@$RHOST:$RPATH

LPATH="/Volumes/G Technology G Speed eS/Studio"
$RSYNC -avz --delete --progress -e "$SSH -i $KEY" "$LPATH" $RUSER@$RHOST:$RPATH

LPATH="/Volumes/G Technology G Speed eS/Toffee Apple"
$RSYNC -avz --delete --progress -e "$SSH -i $KEY" "$LPATH" $RUSER@$RHOST:$RPATH

rm -f "$LOCKFILE"
share|improve this question

2 Answers 2

up vote 4 down vote accepted

If you put the PID of the script into the lock file then, if the lock file exists when a new instance starts, you can read the PID and check if the script is still running. If the script isn't running then clean up, put the PID of the current instance in the lock file and start the rsync otherwise print a 'still running' message and exit.

EDIT:

#!/bin/bash
backup() {
    RSYNC=/usr/bin/rsync
    SSH=/usr/bin/ssh
    KEY=/Users/admin/Documents/Backup/rsync-key
    RUSER=philosophy
    RHOST=example.com
    RPATH=data/
    LPATH="/Volumes/G Technology G Speed eS/Backup"

    $RSYNC -avz --delete --progress -e "$SSH -i $KEY" "$LPATH" $RUSER@$RHOST:$RPATH
}

LOCKFILE=/Users/admin/Documents/backup.isrunning

if [ ! -e "$LOCKFILE" ]
then
    echo $$ >"$LOCKFILE"
    backup
else
    PID=$(cat "$LOCKFILE")
    if kill -0 "$PID" >&/dev/null
    then
        echo "Rsync - Backup still running"
        exit 0
    else
        echo $$ >"$LOCKFILE"
        echo "Warning: previous backup appears not to have finished correctly"
        backup
    fi
fi

rm -f "$LOCKFILE"
share|improve this answer
    
@lain - Can you show me how I would do this in my bash script? I'm no expert at Bash scripting. I know that using $$ would return the PID of the script but how do i check if that PID is running and how do I check it against the file? Thanks –  Brady Feb 21 '11 at 17:38
1  
@Brady: I was hoping you wouldn't ask that as I have no OSX to test with. Hopefully the skeleton above will work. –  Iain Feb 21 '11 at 18:50
    
Thank you lain and grawity for the help with the bash scripting. I have made a few minor changes for my script. I'll post my finished code above. Thanks once again! –  Brady Feb 22 '11 at 10:08

If you are configuring multiple backups then you may wish to take a look at LBackup which offers locking and also fully supports pull backups. More information regarding the advantages of a pull backup is available from the following URL : http://www.lbackup.org/network_backup_strategies

If you check the LBackup source code you will see how the lock system is implemented using a trap. The suggestion above regarding using a PID is also a good idea. With that approach, should the entire server crash and the trap not have a chance to be activated.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.