Whoops.  More testing, new script.  :)

-Robin

#! /bin/bash
#this script contributed by Matthias Meyer
#note that if your $Topdir has been changed, the script will ask you
#the new location.
#
# Significant modifications by Robin Lee Powell, aka
# rlpow...@digitalkingdom.org, all of which are placed into the public domain.
#
usage="\
Usage: $0 -c <client> [-d <backupnumber> -b <before data> [-f] [-n]] | [-l]

Delete specified backups.
Attention!
 If a full backup is deleted, all incremental backups
 that depends on it will also be deleted.

    -c <client>    - client machine for which the backup was made
    -d <number>    - backup number to delete; if this is a full, deletes all
                     dependent incrementals.  Conflicts with -b
    -b <date>      - delete all backups before this date (YYYY-MM-DD); will
                     only remove fulls if all dependent incrementals are gone.
                     Conflicts with -d
    -f             - run Backuppc_nightly afterwards to clean up the pool
    -l             - list all backups for <client>
    -n | --dry-run - Don't actually do anything, just say what would be done
    -h             - this help

Example:
list backups of <client>
 $0 -c <name of the client which was backed up> -l

remove backup #3 from <client>
 $0 -c <name of the client which was backed up> -d 3

remove all backups before 2007-07-02 from <client>
 $0 -c <name of the client which was backed up> -b 2007-07-02
"

typeset -i len

while test $# -gt 0; do
    case "$1" in
    -c | --client )
        shift; client=$1; shift;;
    -b | --before )
        shift; bDate=$1; shift;;
    -d | --delete )
        shift; bNumber=$1; shift;;
    -f | --force )
        nightly="true"; shift;;
    -n | --dry-run )
        dryRun="true"; shift;;
    -l | --list )
        list="true"; shift;;
    * | -h | --help)
        echo "$usage"
        exit 0
        ;;
    esac
done

if [ -z "$client" ] || [ -z $list ] && [ -z $bNumber ] && [ -z $bDate ]
then
    echo "$usage"
    exit 0
fi

if [ "$bNumber" -a "$bDate" ]
then
    echo "Please use either a specific number or a date, not both."
    echo "$usage"
    exit 0
fi

if [ -e /engineyard/etc/backuppc/config.pl ]
then
    TopDir=`grep $Conf{TopDir} /engineyard/etc/backuppc/config.pl | awk '{print 
$3}'`
    len=${#TopDir}-3
    TopDir=${TopDir:1:len}
else
    echo "/engineyard/etc/backuppc/config.pl not found"
    exit 1
fi

ls $TopDir/pc > /dev/null 2>&1
while [ $? != 0 ]
do
    read -p "examined $TopDir seems wrong. What is TopDir ? " TopDir
    ls $TopDir/pc > /dev/null 2>&1
done

ls $TopDir/pc/$client > /dev/null 2>&1
if [ $? != 0 ]
then
    echo "$client have no backups"
    exit 1
fi

if [ ! -z $list ]
then
    while read CLine
    do
        BackupNumber=`echo $CLine | awk '{print $1}'`
        BackupType=`echo $CLine | awk '{print $2}'`
        BackupTime=$(date -d @$(echo $CLine | awk '{ print $4 }'))
        echo "BackupNumber $BackupNumber - $BackupType-Backup from $BackupTime"
    done < $TopDir/pc/$client/backups
    exit 0
fi

if [ ! -z $bNumber ] && [ ! -e $TopDir/pc/$client/$bNumber ]
then
    echo "Backup Number $bNumber does not exist for client $client"
    exit 1
fi

LogDir=`grep $Conf{LogDir} /engineyard/etc/backuppc/config.pl | awk '{print 
$3}'`
len=${#LogDir}-3
LogDir=${LogDir:1:len}

rm -f $TopDir/pc/$client/backups.new > /dev/null 2>&1

#**********************************************************
# Two Processes
#
# Deleting a single backup is very different from deleting
# everything before a date.
#
# If the user specifies a backup number, and the backup is a full,
# well, the user said to delete it, so delete it and everything that
# depends on it.  This means walking the list forwards deleting
# everything until we get to the next full.
#
# On the other hand, if the user asks to delete everything before a
# particular date, and that date comes just after a full, deleting
# the full and all the incrementals is not the expected behaviour at
# all.
#
# As an example: If the first backup is a full on the 5th, and an
# incremental for every day from then on, and it's the 30th, and the
# user says to delete everything older than the 6th, deleting the
# full *and all the incrementals* up to today (i.e. all the
# backups!!) is probably not what they had in mind.
#
# This means that for -b we walk backwards in time so we know if the
# fulls are still needed.
#
# So the two versions actually walk the backup list in opposite
# directions.
#
# -_-
#
# My (Robin Lee Powell) apologies for the resulting code
# duplication.  It's hard to abstract a lot of things in bash.
#
#**********************************************************

delete_dir() {
    dir=$1

    if [ "$dryRun" ]
    then
        echo "not actually removing $dir, in dry run mode"
    else
        echo "remove $dir"
        echo "`date +\"%Y-%m-%d %T\"` BackupPC_deleteBackup delete $dir" >> 
$LogDir/LOG
        rm -fr $dir > /dev/null 2>&1
        echo "`date +\"%Y-%m-%d %T\"` BackupPC_deleteBackup $dir deleted" >> 
$LogDir/LOG
    fi
}

swap_backups_file() {
    if [ "$dryRun" ]
    then
        echo "Not updating the backups list; in dry run mode.  Compare 
$TopDir/pc/$client/backups.new to $TopDir/pc/$client/backups to see what would 
have changed."
    else
        echo "Updating $TopDir/pc/$client/backups"
        cp --backup=t $TopDir/pc/$client/backups $TopDir/pc/$client/backups.old
        # Need to un-revers if doing date-based
        if [ "$bDate" ]
        then
          sort -n $TopDir/pc/$client/backups.new > $TopDir/pc/$client/backups
          rm $TopDir/pc/$client/backups.new
        else
          mv $TopDir/pc/$client/backups.new $TopDir/pc/$client/backups
        fi
        echo "`date +\"%Y-%m-%d %T\"` BackupPC_deleteBackup 
$TopDir/pc/$client/backups updated" >> $LogDir/LOG
    fi
}

#*************************
# -d / forwards / delete a full and all its friends handling
#*************************

if [ "$bNumber" ]
then
    delete2full="false"
    while read CLine
    do
        BackupNumber=`echo $CLine | awk '{print $1}'`
        BackupTime=$(echo $CLine | awk '{ print $4 }')
        BackupType=`echo $CLine | awk '{print $2}'`
        if [ $BackupType == "full" ]
        then
            delete2full="false"
        fi

        if [ $BackupNumber == "$bNumber" ] || [ $delete2full == "true" ]
        then
            if [ $BackupType == "full" ]
            then
                if [ $delete2full == "false" ]
                then
                    delete2full="true"
                else
                    delete2full="false"
                fi
            fi
            bNumber=$BackupNumber
            delete_dir $TopDir/pc/$client/$bNumber
        fi
        if [ "$BackupNumber" != "$bNumber" ]
        then
            echo "$CLine" >> $TopDir/pc/$client/backups.new
        fi
    done < $TopDir/pc/$client/backups

    swap_backups_file

fi

#*************************
# -b / backwards / delete a full only if all dependents are gone handling
#*************************
# What we do here is walk the list of backups backwards in time.  If we skip
# over an incremental, we mark a flag that says we need the corresponding full.
# When we hit a full, we clear that flag.

if [ "$bDate" ]
then
    needFull=""
    sort -rn $TopDir/pc/$client/backups | while read CLine
    do
        BackupNumber=`echo $CLine | awk '{print $1}'`
        BackupTime=$(echo $CLine | awk '{ print $4 }')
        BackupType=`echo $CLine | awk '{print $2}'`

        testTime=$(date -d "$bDate" +%s)

        removed=""

        if [ "$BackupTime" -lt "$testTime" ]
        then
            if [ $BackupType == "full" -a "$needFull" ]
            then
                echo "Not deleting backup number $BackupNumber ; it is a full 
and there still exist incrementals that depend on it."
            else
                removed="true"
                delete_dir $TopDir/pc/$client/$BackupNumber
            fi
        else
            if [ $BackupType != "full" ]
            then
                needFull="true"
            fi
        fi
        # Clear the flag whether the backup was selected or not
        if [ $BackupType == "full" ]
        then
            needFull=""
        fi      
        if [ ! "$removed" ]
        then
            echo "$CLine" >> $TopDir/pc/$client/backups.new
        fi
    done
    swap_backups_file
fi

#*************************
# Run nightly cleanup, if requested
#*************************
if [ ! -z $nightly ]
then
    if [ "$dryRun" ]
    then
        echo "Not doing a nightly run; in dry run mode."
    else
        path=${0%/BackupPC*}
        su backuppc -c "$path/BackupPC_serverMesg BackupPC_nightly run"
        su backuppc -c "$path/BackupPC_serverMesg log I honestly apologize for 
the inconvenience"
        echo `date "+%Y-%m-%d %T"` BackupPC_deleteBackup BackupPC_nightly 
politely scheduled via daemon >> $LogDir/LOG
    fi
fi

exit $?
------------------------------------------------------------------------------
Beautiful is writing same markup. Internet Explorer 9 supports
standards for HTML5, CSS3, SVG 1.1,  ECMAScript5, and DOM L2 & L3.
Spend less time writing and  rewriting code and more time creating great
experiences on the web. Be a part of the beta today.
http://p.sf.net/sfu/beautyoftheweb
_______________________________________________
BackupPC-users mailing list
BackupPC-users@lists.sourceforge.net
List:    https://lists.sourceforge.net/lists/listinfo/backuppc-users
Wiki:    http://backuppc.wiki.sourceforge.net
Project: http://backuppc.sourceforge.net/

Reply via email to