Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 238 lines (212 sloc) 7.59 KB
#!/usr/bin/env bash
#See README @ http://github.com/Gestas/Tarsnap-generations/blob/master/README
#########################################################################################
#What day of the week do you want to take the weekly snapshot? Default = Friday(5) #
WEEKLY_DOW=5 #
#What hour of the day to you want to take the daily snapshot? Default = 11PM (23) #
DAILY_TIME=23 #
#Do you want to use UTC time? (1 = Yes) Default = 0, use local time. #
USE_UTC=0 #
#Path to GNU date binary (e.g. /bin/date on Linux, /usr/local/bin/gdate on FreeBSD) #
DATE_BIN=`which date` #
#########################################################################################
usage ()
{
cat << EOF
usage: $0 arguments
This script manages Tarsnap backups
ARGUMENTS:
? Display this help.
-f Path to a file with a list of folders to be backed up. List should be \n delimited.
-h Number of hourly backups to retain.
-d Number of daily backups to retain.
-w Number of weekly backups to retain.
-m Number of monthly backups to retain.
-q Be quiet - only output if something goes wrong
For more information - http://github.com/Gestas/Tarsnap-generations/blob/master/README
EOF
}
#Declaring helps check for errors in the user-provided arguments. See line #69.
declare -i HOURLY_CNT
declare -i DAILY_CNT
declare -i WEEKLY_CNT
declare -i MONTHLY_CNT
declare -i QUIET
QUIET=0
#Get the command line arguments. Much nicer this way than $1, $2, etc.
while getopts ":f:h:d:w:m:q" opt ; do
case $opt in
f ) PATHS=$OPTARG ;;
h ) HOURLY_CNT=$(($OPTARG+1)) ;;
d ) DAILY_CNT=$(($OPTARG+1)) ;;
w ) WEEKLY_CNT=$(($OPTARG+1)) ;;
m ) MONTHLY_CNT=$(($OPTARG+1)) ;;
q ) QUIET=1 ;;
\?) echo \n $usage
exit 1 ;;
*) echo \n $usage
exit 1 ;;
esac
done
#Check arguments
if ( [ -z "$PATHS" ] || [ -z "$HOURLY_CNT" ] || [ -z "$DAILY_CNT" ] || [ -z "$WEEKLY_CNT" ] || [ -z "$MONTHLY_CNT" ] )
then
echo "-f, -h, -d, -w, -m are not optional."
usage
exit 1
fi
if [ ! -f $PATHS ]
then
echo "Couldn't find file $PATHS"
usage
exit 1
fi
#Check that $HOURLY_CNT, $DAILY_CNT, $WEEKLY_CNT, $MONTLY_CNT are numbers.
if ( [ $HOURLY_CNT = 1 ] || [ $DAILY_CNT = 1 ] || [ $WEEKLY_CNT = 1 ] || [ $MONTHLY_CNT = 1 ] )
then
echo "-h, -d, -w, -m must all be numbers greater than 0."
usage
exit 1
fi
#Set some constants
#The day of the week (Monday = 1, Sunday = 7)
DOW=$($DATE_BIN +%u)
#The calendar day of the month
DOM=$($DATE_BIN +%d)
#The last day of the current month. I wish there was a better way to do this, but this seems to work everywhere.
LDOM=$(echo $(cal) | awk '{print $NF}')
#We need 'NOW' to be constant during execution, we set it here.
NOW=$($DATE_BIN +%Y%m%d-%H)
CUR_HOUR=$($DATE_BIN +%H)
if [ "$USE_UTC" = "1" ] ; then
NOW=$($DATE_BIN -u +%Y%m%d-%H)
CUR_HOUR=$($DATE_BIN -u +%H)
fi
#Find the backup type (HOURLY|DAILY|WEEKLY|MONTHY)
BK_TYPE=HOURLY #Default to HOURLY
if ( [ "$DOM" = "$LDOM" ] && [ "$CUR_HOUR" = "$DAILY_TIME" ] ) ; then
BK_TYPE=MONTHLY
else
if ( [ "$DOW" = "$WEEKLY_DOW" ] && [ "$CUR_HOUR" = "$DAILY_TIME" ] ) ; then
BK_TYPE=WEEKLY
else
if [ "$CUR_HOUR" = "$DAILY_TIME" ] ; then
BK_TYPE=DAILY
fi
fi
fi
#Take the backup with the right name
if [ $QUIET != "1" ] ; then
echo "Starting $BK_TYPE backups..."
fi
for dir in $(cat $PATHS) ; do
tarsnap -c -f $NOW-$BK_TYPE-$(hostname -s)-$(echo $dir) --one-file-system -C / $dir
if [ $? = 0 ] ; then
if [ $QUIET != "1" ] ; then
echo "$NOW-$BK_TYPE-$(hostname -s)-$(echo $dir) backup done."
fi
else
echo "$NOW-$BK_TYPE-$(hostname -s)-$(echo $dir) backup error. Exiting" ; exit $?
fi
done
#Check to make sure the last set of backups are OK.
if [ $QUIET != "1" ] ; then
echo "Verifying backups, please wait."
fi
archive_list=$(tarsnap --list-archives)
for dir in $(cat $PATHS) ; do
case "$archive_list" in
*"$NOW-$BK_TYPE-$(hostname -s)-$(echo $dir)"* )
if [ $QUIET != "1" ] ; then
echo "$NOW-$BK_TYPE-$(hostname -s)-$(echo $dir) backup OK."
fi ;;
* ) echo "$NOW-$BK_TYPE-$(hostname -s)-$(echo $dir) backup NOT OK. Check --archive-list."; exit 3 ;;
esac
done
#Delete old backups
HOURLY_DELETE_TIME=$($DATE_BIN -v-$HOURLY_CNT$"H" +%Y%m%d-%H)
DAILY_DELETE_TIME=$($DATE_BIN -v-$DAILY_CNT$"d" +%Y%m%d-%H)
WEEKLY_DELETE_TIME=$($DATE_BIN -v-$WEEKLY_CNT$"w" +%Y%m%d-%H)
MONTHLY_DELETE_TIME=$($DATE_BIN -v-$MONTHLY_CNT$"m" +%Y%m%d-%H)
if [ $QUIET != "1" ] ; then
echo "Finding backups to be deleted."
fi
if [ $BK_TYPE = "HOURLY" ] ; then
for backup in $archive_list ; do
case "$backup" in
"$HOURLY_DELETE_TIME-$BK_TYPE"* )
case "$backup" in #this case added to make sure the script doesn't delete the backup it just took. Case: '-h x' and backup takes > x hours.
*"$NOW"* ) echo "Skipped $backup" ;;
* ) tarsnap -d -f $backup
if [ $? = 0 ] ; then
if [ $QUIET != "1" ] ; then
echo "$backup snapshot deleted."
fi
else
echo "Unable to delete $backup. Exiting" ; exit $?
fi ;;
esac ;;
* ) ;;
esac
done
fi
if [ $BK_TYPE = "DAILY" ] ; then
for backup in $archive_list ; do
case "$backup" in
"$DAILY_DELETE_TIME-$BK_TYPE"* )
case "$backup" in
*"$NOW"* ) echo "Skipped $backup" ;;
* ) tarsnap -d -f $backup
if [ $? = 0 ] ; then
if [ $QUIET != "1" ] ; then
echo "$backup snapshot deleted."
fi
else
echo "Unable to delete $backup. Exiting" ; exit $?
fi ;;
esac ;;
* ) ;;
esac
done
fi
if [ $BK_TYPE = "WEEKLY" ] ; then
for backup in $archive_list ; do
case "$backup" in
"$WEEKLY_DELETE_TIME-$BK_TYPE"* )
case "$backup" in
*"$NOW"* ) echo "Skipped $backup" ;;
* ) tarsnap -d -f $backup
if [ $? = 0 ] ; then
if [ $QUIET != "1" ] ; then
echo "$backup snapshot deleted."
fi
else
echo "Unable to delete $backup. Exiting" ; exit $?
fi ;;
esac ;;
* ) ;;
esac
done
fi
if [ $BK_TYPE = "MONTHLY" ] ; then
for backup in $archive_list ; do
case "$backup" in
"$MONTHLY_DELETE_TIME-$BK_TYPE"* )
case "$backup" in
*"$NOW"* ) echo "Skipped $backup" ;;
* ) tarsnap -d -f $backup
if [ $? = 0 ] ; then
if [ $QUIET != "1" ] ; then
echo "$backup snapshot deleted."
fi
else
echo "Unable to delete $backup. Exiting" ; exit $?
fi ;;
esac ;;
* ) ;;
esac
done
fi
if [ $QUIET != "1" ] ; then
echo "$0 done"
fi