Disaster Recovery

Automate subversion backups


Subversion is increasing in popularity and usage, and while it makes a fantastic version control system -- as with all things -- it needs to be properly backed up. If subversion is used as a version control or backup system for other data (i.e., configuration files, as we've seen in a previous tip), then that data becomes exceptionally important, and "backing up the backup" would be a wise thing to do.

Fortunately, subversion gives us the tools and flexibility to do this easily. With a monthly full backup and on-the-fly backups of each commit, backing up subversion can be painless and protects against the rare case of data corruption.

The first thing is to add a post-commit hook to do a dump of each commit as it is made. Assuming the subversion repository is stored in /subversion/repos/mystuff, modify /subversion/repos/mystuff/hooks/post-commit and add:

svnadmin dump "$REPOS" --revision "$REV" --incremental >/subversion/backup/incremental/mystuff/commit-$REV

The backup directory will be /subversion/backup/incremental/mystuff and every commit will be dumped to that directory as "commit-52" for commit number 52.

If you do not already have the post-commit file, simply copy the skeleton post-commit.tmpl file to create it.

To create monthly backups, two things are desired: first is a full hotcopy of the subversion repository and then setting new dump baselines for subsequent commits. On a busy subversion server, the incremental dumps can quickly add up, so every month a new full dump is done to create a baseline and the previous month's commits are removed (as they are part of the new baseline). The script below accomplishes this. To automate it, create it as /etc/cron.monthly/svn-fullbackup:

#!/bin/sh

date="`date +%Y-%m`"

svnbasedir="/subversion/repos"

svnfullbkdir="/subversion/backup/full"

svnincbkdir="/subversion/backup/incremental"

echo "+++ Backing up subversion repositories..."

for repo in mystuff ; do

    echo ""

    mkdir -p ${svnfullbkdir}/${date}

    /usr/bin/hot-backup.py ${svnbasedir}/${repo} ${svnfullbkdir}/${date}

    if [ "$?" != "0" ]; then

        echo "!! Hot backup failed on repository: ${repo}"

    fi

    lastrev="`svnlook youngest ${svnbasedir}/${repo}`"

    echo "** Creating new baseline for ${repo} (at revision ${lastrev})..."

    mkdir -p ${svnincbkdir}/${repo}.tmp

    svnadmin dump -q ${svnbasedir}/${repo} >${svnincbkdir}/${repo}.tmp/baseline-${lastrev}

    if [ "$?" == "0" ]; then

        rm -f ${svnincbkdir}/${repo}/{baseline,commit}*

        mv -f ${svnincbkdir}/${repo}.tmp/baseline-${lastrev} ${svnincbkdir}/${repo}/

    else

        echo "!! Creating new baseline failed!  Left the old baseline and commits intact!"

    fi

    rm -rf ${svnincbkdir}/${repo}.tmp

done

Depending on how subversion is installed, the path to hot-backup.py may need to be adjusted; that script comes with subversion and its resulting installed location may depend on how the vendor packaged subversion for your particular Linux distribution.

Now, every month, a new baseline dump of the entire repository is created both as a text dump, which can easily be reloaded in the case of problems with the subversion repository, and also a hot backup of the full repository. If worse comes to worse, the repository can be restored from the hot backup and then subsequent changes can be reloaded with the incremental dumps the repository performs on every commit.

As well, because each hot dump goes to its own dated directory, you can roll back the repository to a specific point in time if required. The script could probably be made more robust for high-activity repositories so that Apache would be stopped prior to the backup and restored after the backup (if feasible, and assuming the use of Apache to front-end the repository in the first place) to prevent any commits to the repository during the backup. You could also perform verification on the repository prior to doing the backup to ensure the backup is okay; however, I recommend doing a daily verify on the database to ensure you spot problems as soon as they arise. This can be done by creating /etc/cron.daily/svn-verify with:

#!/bin/sh

svnbasedir="/subversion/repos"

echo "Verifying subversion repositories..."

for repo in mystuff ; do

    printf "Verifying: ${repo}\t\t"

    svnadmin verify ${svnbasedir}/${repo} >/dev/null 2>&1

    if [ "$?" != "0" ]; then

        printf "  FAILED!\n"

    else

        printf "  ok\n"

    fi

done

Of course, in either script you can verify/back up more than one subversion repository by changing for repo in mystuff to for repo in mystuff stuff private to perform the actions on the repositories mystuff, stuff, and private.

Delivered each Tuesday, TechRepublic's free Linux NetNote provides tips, articles, and other resources to help you hone your Linux skills. Automatically sign up today!

About

Vincent Danen works on the Red Hat Security Response Team and lives in Canada. He has been writing about and developing on Linux for over 10 years and is a veteran Mac user.

3 comments
pankaj_dangi1
pankaj_dangi1

1. How to configure a local web server of Apache, for SVN. I hav tried a lot. but i m unable to configure it. 2. Second thing what should be the url for to checkout repository, and file.. Please give a suggestion.

vdanen
vdanen

Why do you want to setup apache for svn if you're just going to be using it on the local machine? If you're just going to use svn on the one machine, just setup an svn repository and use file:/// to access it. If you do need to setup apache for svn, do a search here.. I've written a piece on how to do that already. =) Also, I imagine your url to checkout would be http://localhost/... (the rest depends on how you set it up, of course).

Editor's Picks