I run a small Subversion server for my personal software projects and other things one would want to put under version control. Never knowing when the ugly sound of a dying hard drive will sneak up on me, I needed some kind of script to do daily backups of the repositories. After checking my options, I decided I would be doing hotcopies of the repositories piped to tar with bz2 compression and send the resulting archives over to another machine using scp, handling password-less authentication with an SSH key pair.
Since I’m insane (more than most, in any case), I wrote a bash shell script. Here it is:
#!/bin/bash
##
## svn-backup.sh -- Daily backup script for subversion repositories
## Copyright (c) 2005, Jean-Francois Roy
##
## CONFIGURATION
# local path to the repositories
svnroot="/usr/local/svn"
# install path of subversion (where svnadmin and svnlook may be found)
svninstallroot="/opt/local/bin"
# remote host for scp, including any required user and password
remotehost="bahamut@zohar.local"
# path on remote host where the repository archives will be uploaded
remotedir="Documents/Backups/subversion/`date +%d-%m-%G`"
## CODE
# check parameters
if [ -z ${svnroot} ] || [ ! -d ${svnroot} ]
then
echo “FATAL: invalid svnroot variable”
exit
fi
if [ -z ${svninstallroot} ] || [ ! -d ${svninstallroot} ]; then
echo “FATAL: invalid svninstallroot variable”
exit
fi
if [ ! -x ${svninstallroot}/svnlook ] || [ ! -x ${svninstallroot}/svnadmin ]; then
echo “FATAL: could not find Subversion in provided install path”
exit
fi
if [ -z ${remotehost} ]; then
echo “FATAL: invalid remotehost variable”
exit
fi
if [ -z ${remotedir} ]; then
echo “FATAL: invalid remotedir variable”
exit
fi
# announce that we’re running
echo “Running svn-backup.sh at `date`”
# perform a mkdir on the remote host
ssh ${remotehost} “mkdir -p ${remotedir}”
# change into the current dir
cd ${svnroot}
for filename in *
do
# get the current revision
revision=`${svninstallroot}/svnlook youngest “${filename}”`
# keep the user happy
echo “Backing up ${filename} r${revision}”
# make sure the repo is OK
echo ” —> Recovering the repository”
${svninstallroot}/svnadmin recover –wait “${filename}” > /dev/null
# did the recover operation fail?
if [ $? -ne 0 ]; then
echo ” Backup of ${filename} r${revision} failed because recovery failed!”
break
fi
# create the backup folder
base=”$RANDOM”
if [ -e "/tmp/${base}" ]
then
rm -Rf “/tmp/${base}”
fi
mkdir “/tmp/${base}”
# hotcopy
echo ” —> Hotcopying the repository”
${svninstallroot}/svnadmin hotcopy –clean-logs “${filename}” “/tmp/${base}/${filename}”
# did the hotcopy fail?
if [ $? -ne 0 ]; then
echo “Backup of ${filename} r${revision} failed because hotcopy failed!”
rm -Rf “/tmp/${base}”
break
fi
# compress the hotcopy
echo ” —> Packaging the repository in a tar.bz2 archive”
archive=”${filename}-r${revision}.tar.bz2″
tar -cjpf “/tmp/${base}/${archive}” -C “/tmp/${base}” “${filename}”
# send it over
echo ” —> Copying repository archive to remote host”
scp -B -q “/tmp/${base}/${archive}” “${remotehost}:${remotedir}/${archive}”
# done with the backup folder
echo ” —> Cleaning up”
rm -Rf “/tmp/${base}”
done
echo “svn-backup.sh completed at `date`”
echo “”
