Tuesday, September 22, 2009

Bash Scripting

I had some bash scripts to write a little while ago and I thought I'd share them here.

Let's start with a simple task. Say we have a load of files in a directory, e.g. null121231.xml, null3049432.xml etc. and we want to remove null from the start of the files' names:

for f in null*; do mv "$f" "${f#null}"; done

Moving onto a little more complex. I wanted to write a script that would backup these files to another machine. I felt it was more logical to trigger this script from the remote machine so I did it this way:

Remote machine: telex
Local machine (where backup is being stored): hossbox

#!/bin/bash
# Off site backup script for live database
#
#
# DATE: 27/08/2009

#################################
# Assign Date variables     #
#################################
startTime=`date`
LOGFILE=/home/java/blog_backup_jobs.txt

echo $startTime ": Starting blog backup" >> $LOGFILE

# Ping interval in seconds
PINGINTERVAL=600
numErrors=0
HOST=telex

#### functions ####
function pinghost()
{
    ping -c 1 $1 &> /dev/null
    if [ $? = 0 ]; then
        return 0
    else
        return 111
    fi
}

function notifyAdmin()
{
    # email subject
    SUBJECT="Blog backup failed, mecca failed to respond for 1 hour"
    # Email to?
    EMAIL="patrick@localhost"
    # Email text/message
    EMAILMESSAGE="/home/java/cron/emailmessage.txt"
    echo "$HOST has failed to respond for 1 hour. The blog backup script has failed" > $EMAILMESSAGE
    # Send email using /bin/mail
    /bin/mail -s "$SUBJECT" "$EMAIL" < $EMAILMESSAGE
}


#### Script starts here ####

pinghost $HOST
errorCode=$?

while [ $errorCode -eq 111 ]
do
    numErrors=$(( $numErrors + 1 ))
    echo "`date +%r`: Ping error $numErrors to $HOST" >> $LOGFILE

    if [ $numErrors -eq 6 ]; then
        echo "`date +%r`: Couldn't ping $HOST for 1 hour, emailing admin.." >> $LOGFILE
        # calling a function to email someone here
        notifyAdmin
        echo "`date +%r`: mail sent....exiting." >> $LOGFILE
        exit 1
    else
        sleep $PINGINTERVAL
        pinghost $HOST
        errorCode=$?
    fi
done

# If we're here then mecca is up. Now we need to connect and
# check if the blog extraction job is finished
# returns 202 if the pid file exits
# returns 0 if it doesn't
PIDFILE=/home/java/extract_blog.pid
function checkBlogJobFinished()
{
    if ssh $HOST 'ls "'$PIDFILE'" >/dev/null'; then
        return 202;
    else
        return 0;
    fi
}

checkBlogJobFinished
errorCode=$?
numChecks=0
# time to sleep in seconds, 7200seconds = 2 hours
SLEEPTIME=7200
while [ $errorCode -eq 202 ]
do
    numChecks=$(( $numChecks + 1 ))
    echo "`date +%r`: Check $numChecks: job still running, going to sleep for $SLEEPTIME seconds" >> $LOGFILE
    sleep $SLEEPTIME
    checkBlogJobFinished
    errorCode=$?
done

# If we're here then the blog job has finished, time to get the blog xml files

########################################
# Backup Site Directory - files        #
########################################

# remote blog folder is of format: week{currentWeekNo_currentYear}
remoteBlogFolder=/home/java/extractor/blogs/week`date +%V_%Y`
localBlogFolder=/home/java/backup/mecca/blogs

if [ ! -e $localBlogFolder ]
then
    mkdir -p $localBlogFolder
fi

echo "`date +%r`: Starting retreival of $remoteBlogFolder" >> $LOGFILE
rsync -avz -e "ssh -i /home/java/cron/hossbox-rsync-key-java" java@$HOST:$remoteBlogFolder $localBlogFolder
echo "`date +%r`: Ending retreival of $remoteBlogFolder" >> $LOGFILE

currentWeek=`date +%V`
let previousWeek=$currentWeek-1

oldBackupFolder=/home/java/backup/telex/blogs/week$previousWeek

# remove old backup
if [ -e $oldBackupFolder ]
then
    rm -rf $oldBackupFolder
fi

endTime=`date`
echo $endTime ": Ending blog backup" >> $LOGFILE

This script sleeps for 2 hours if a blog extraction job is running on the remote machine. It sleeps for 10 minutes if the remote machine isn't responding.

No comments: