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 ""

© 2011 /dev/klog Suffusion theme by Sayontan Sinha