rsync+zfs rotate script

Kevin Kramer kramer at centtech.com
Thu Oct 8 15:49:32 MDT 2009


here is my script to rsync a directory to a zfs filesystem, rotate 
existing snapshots, then create a "latest" snapshot.

work to be done

- check for an include/exclude list for the rsync command
- create a monthly snapshot

be careful of possible line wraps

#!/bin/sh


RSYNC_CMD="/usr/local/bin/rsync -axS --delete-delay --stats"

# first argument is the remote server to connect (ie. server1)
# second argument is the remote target (ie. /home/) note trailing slashes just like in rsync
# third argument is which pool to use (ie. tank)
# fourth argument is what ZFS fileystem on that pool (ie server1/home)
# fifth argument is how many snapshots for this zfs filesystem

RMT_SERVER=$1
RMT_TARGET=$2
LCL_POOL=$3
LCL_ZFS=$4
SNAPCOUNT=$5

OUTFILE=/tmp/rsync_zfs_rotate-${LCL_POOL}-${LCL_ZFS}.log
ERRFILE=/tmp/rsync_zfs_rotate-${LCL_POOL}-${LCL_ZFS}.err
MAILER=/usr/sbin/sendmail
MAILTO=someone at domain.com

# NO EDITS BELOW THIS
###################################################

# remove any old ERRFILE/OUTFILE to start fresh
rm -f ${OUTFILE}
rm -f ${ERRFILE}

echo "" > $OUTFILE
echo "----------------- RSYNC BEGIN  ----------------" >> $OUTFILE
date >> $OUTFILE
echo "" >> $OUTFILE
echo "$RSYNC_CMD $RMT_SERVER:$RMT_TARGET /$LCL_POOL/$LCL_ZFS" >> $OUTFILE

$RSYNC_CMD $RMT_SERVER:$RMT_TARGET /$LCL_POOL/$LCL_ZFS 2> $ERRFILE >> $OUTFILE

ERR=$?
if [ "$ERR" != "0" ] ; then
        if [ "$ERR" != "24" ] ; then
        echo "Rsync Error Code $ERR" ;
        cat $ERRFILE | mailx -s "RSYNC BACKUP ERROR - ${RMT_SERVER}:${RMT_TARGET}" ${MAILTO} ;
        exit ;
        fi ;
fi ;

echo "" >> $OUTFILE
date >> $OUTFILE
echo "------------------  RSYNC END ------------------" >> $OUTFILE
echo "" >> $OUTFILE
echo "" >> $OUTFILE
echo "" >> $OUTFILE
echo "---------------  BEGIN ZFS ROTATION ------------------" >> $OUTFILE
date >> $OUTFILE
echo "" >> $OUTFILE
echo "Number of snapshots to keep=${SNAPCOUNT}"
SNAPPATH=/${LCL_POOL}/${LCL_ZFS}/.zfs/snapshot
NEWSNAP=${SNAPCOUNT} ;

# destroy the oldest ($SNAPCOUNT) if exists
if [ -d ${SNAPPATH}/${SNAPCOUNT} ] ; then
        echo "" ;
        echo "Found ${LCL_POOL}/${LCL_ZFS}@${SNAPCOUNT}" ;
        echo "destroying snapshot ${SNAPCOUNT} found for ${LCL_ZFS}" ;
        echo "zfs destroy ${LCL_POOL}/${LCL_ZFS}@${SNAPCOUNT}" ;
        echo "destroying snapshot ${SNAPCOUNT} found for ${LCL_ZFS}" >> $OUTFILE ;
        echo "zfs destroy ${LCL_POOL}/${LCL_ZFS}@${SNAPCOUNT}" >> $OUTFILE ;
        zfs destroy ${LCL_POOL}/${LCL_ZFS}@${SNAPCOUNT} 2> $ERRFILE ;
        SNAPCOUNT=`expr $SNAPCOUNT - 1` ;
        echo "" ;
        echo "" ;
fi ;

# start searching for the others
until [  $SNAPCOUNT -lt 1 ]; do
        echo "Looking for ${LCL_POOL}/${LCL_ZFS}@${SNAPCOUNT}" ;
        if [ -d ${SNAPPATH}/${SNAPCOUNT} ]; then
                OLDSNAP=${SNAPCOUNT} ;
                NEWSNAP=${OLDSNAP} ;
                NEWSNAP=`expr $NEWSNAP + 1` ;
                echo "SNAPCOUNT = ${SNAPCOUNT} NEWSNAP = ${NEWSNAP}" ;
                echo "Found ${LCL_POOL}/${LCL_ZFS}@${OLDSNAP}" ;
                echo "" ;
                echo "zfs rename ${LCL_POOL}/${LCL_ZFS}@${OLDSNAP} ${LCL_POOL}/${LCL_ZFS}@${NEWSNAP}" ;
                echo "zfs rename ${LCL_POOL}/${LCL_ZFS}@${OLDSNAP} ${LCL_POOL}/${LCL_ZFS}@${NEWSNAP}" >> $OUTFILE ;
                zfs rename ${LCL_POOL}/${LCL_ZFS}@${OLDSNAP} ${LCL_POOL}/${LCL_ZFS}@${NEWSNAP}  2>> $ERRFILE ;
                SNAPCOUNT=`expr $SNAPCOUNT - 1` ;
                echo "" ;
                echo "" ;
        else
                OLDSNAP=${SNAPCOUNT} ;
                NEWSNAP=${OLDSNAP} ;
                NEWSNAP=`expr $NEWSNAP + 1` ;
                echo "SNAPCOUNT = ${SNAPCOUNT} NEWSNAP = ${NEWSNAP}" ;
                echo "${LCL_POOL}/${LCL_ZFS}@${OLDSNAP} not found";
                echo "${LCL_POOL}/${LCL_ZFS}@${OLDSNAP} not found" >> $OUTFILE ;
                SNAPCOUNT=`expr $SNAPCOUNT - 1` ;
                echo "" ;
                echo "" ;
        fi ;
done ;

# now rotate latest to 1 if exists
if [ -d ${SNAPPATH}/latest ]; then
        echo "Found ${LCL_POOL}/${LCL_ZFS}@latest" ;
        echo "" ;
        zfs rename ${LCL_POOL}/${LCL_ZFS}@latest ${LCL_POOL}/${LCL_ZFS}@1 2>> $ERRFILE ;
        echo "zfs rename ${LCL_POOL}/${LCL_ZFS}@latest ${LCL_POOL}/${LCL_ZFS}@1" ;
        echo "zfs rename ${LCL_POOL}/${LCL_ZFS}@latest ${LCL_POOL}/${LCL_ZFS}@1" >> $OUTFILE ;
        echo "" ;
fi ;

# create the latest snapshot
echo "Creating latest snapshot" ;
zfs snapshot ${LCL_POOL}/${LCL_ZFS}@latest 2>> $ERRFILE ;
echo "zfs snapshot ${LCL_POOL}/${LCL_ZFS}@latest" ;
echo "zfs snapshot ${LCL_POOL}/${LCL_ZFS}@latest" >> $OUTFILE ;
echo "" >> $OUTFILE

date >> $OUTFILE
echo "---------------  END ZFS ROTATION ------------------" >> $OUTFILE
echo "" >> $OUTFILE

# now we will send an email with all this

if [ -s ${ERRFILE} ]; then
        cat $ERRFILE | mailx -s "BACKUP ERROR - ${RMT_SERVER}:${RMT_TARGET}" ${MAILTO} ;
        cat $OUTFILE | mailx -s "BACKUP REPORT - ${RMT_SERVER}:${RMT_TARGET}" ${MAILTO} ;
else
        cat $OUTFILE | mailx -s "BACKUP REPORT - ${RMT_SERVER}:${RMT_TARGET}" ${MAILTO} ;
fi ;




More information about the rsync mailing list