Following up on the good work of Jean-Francois Roy, here's my slightly
extended version of his script (Update: sorry, the link is dead ) to
backup all Subversion repositories to a remote host.
How to use:
Download
backup-all-svn.sh
chmod u+x path/to/ backup-all-svn.sh
./backup-all-svn.sh -h target_host
(can also set
target port and user name)
Some features:
Works with plain /bin/sh
, so it should work on any Linux / BSD
distribution.
Works with repository names with spaces and non-ASCII characters.
#!/bin/sh
#
# $Id: backup-all-svn.sh 387 2008-06-07 20:36:08Z vengmark $
#
# NAME
# backup-all-svn.sh - Backup all Subversion repositories
#
# SYNOPSIS
# backup-all-svn.sh [options]
#
# OPTIONS
# -v Verbose output
# -h Target host name (mandatory)
# -p Target host port
# -u Target host user name
#
# EXAMPLE
# ./backup-all-svn.sh -v -h example.com -p 1234 -u johndoe
#
# DESCRIPTION
# Backups all your subversion repositories to a remote machine.
#
# The current user must have access to the subversion repositories.
# To work around this, you should `sudo adduser <username> <div>`
# and `sudo chmod -R g+w /path/to/repos`.
#
# To avoid having to type your password several times, you can setup SSH
# keys - See e.g. https://help.ubuntu.com/community/SSHHowto
#
# BUGS
# Email bugs to victor dot engmark at gmail dot com. Please include the
# output of running this script in verbose mode (-v).
#
# COPYRIGHT AND LICENSE
# Copyright (C) 2005 Jean-Francois Roy
# Copyright (C) 2008 Victor Engmark
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
# Init
ifs_original = " $IFS " # Reset when done
PATH = "/usr/bin:/bin"
cmdname = ` basename $0 `
directory = ` dirname $0 `
# Remote host
target_dir = ".svn-backup/ ` date +%G-%m-%d` "
target_port = 22
target_user = ` whoami `
# Subversion
svn_root = "/var/lib/svn"
svn_install_root = "/usr/bin"
# Error messages from /usr/include/sysexits.h, recommended by
# http://www.faqs.org/docs/abs/HTML/exitcodes.html
EX_OK = 0
EX_USAGE = 64
EX_CANT_CREATE = 73
# Custom errors
EX_NO_SUCH_DIR = 91
EX_NO_SUCH_EXEC = 92
usage_error()
{
echo "Usage: ${ cmdname } [-v] -h host [-p port] [-u user]" #Code 3
exit $EX_USAGE
}
# Process parameters
until [ $# -eq 0 ]
do
case $1 in
-v )
verbose = 1
shift
;;
-h )
if [ -z " $2 " ]
then
usage_error
fi
target_host = $2
shift 2
;;
-p )
if [ -z " $2 " ]
then
usage_error
fi
target_port = $2
shift 2
;;
-u )
if [ -z " $2 " ]
then
usage_error
fi
target_user = $2
shift 2
;;
* )
#Unknown parameter
usage_error
;;
esac
done
if [ -z ${ target_host } ]
then
usage_error
fi
# Use for mandatory directory checks
# $1 is the directory path
# $2 is the (optional) error message
check_directory()
{
if [ ! -d $1 ]
then
echo "No such directory: ' ${ 1 } '" > &2
echo $2 > &2
exit $EX_NO_SUCH_DIR
fi
}
check_directory $svn_root "Please change \$ svn_root to point to the directory where your Subversion repositories are."
check_directory $svn_install_root "Please change \$ svn_install_root to point to the directory where Subversion is installed."
# Make sure an executable is available
# $1 is the path to the executable
# $2 is the (optional) error message
check_executable()
{
if [ ! -x $1 ]
then
echo "No such executable: ' ${ 1 } '" > &2
echo $2 > &2
exit $EX_NO_SUCH_EXEC
fi
}
svn_install_missing = "Please change \$ svn_install_root to point to the directory where Subversion is installed."
check_executable ${ svn_install_root } /svnlook $svn_software_missing
check_executable ${ svn_install_root } /svnadmin $svn_software_missing
# Create the temporary folder
temp_dir = ` mktemp -t -d ${ cmdname } .XXXXXXXXXX` || exit $?
verbose_echo()
{
if [ $verbose ]
then
echo " $* "
fi
}
# Announce that we're running
verbose_echo "Running $cmdname at ` date ` ."
# Create target directory
ssh -p ${ target_port } ${ target_user } @${ target_host } "mkdir -p \" ${ target_dir } \" " || exit $?
# Loop over repositories
cd " ${ svn_root } "
IFS = "
" # Make sure paths with spaces don't make any trouble when looping
for repository in *
do
# Get the last revision
revision = ` ${ svn_install_root } /svnlook youngest " ${ repository } " `
verbose_echo "Backing up repository \" ${ repository } \" revision ${ revision } ."
# Make sure the repo is OK
verbose_echo "Recovering the repository."
${ svn_install_root } /svnadmin recover --wait " ${ repository } " > /dev/null
# Did the recover operation fail?
if [ $? -ne 0 ]
then
echo "Backup failed because recovery failed." > &2
break
fi
# Hotcopy
verbose_echo "Hot-copying the repository."
${ svn_install_root } /svnadmin hotcopy --clean-logs " ${ repository } " " $temp_dir / ${ repository } "
# Did the hotcopy fail?
if [ $? -ne 0 ]
then
echo "Backup failed because hotcopy failed." > &2
rm -Rf " $temp_dir "
break
fi
# Compress the hotcopy
verbose_echo "Compressing the repository in a tar.bz2 archive."
archive = " ${ repository } -r ${ revision } .tar.bz2"
tar -cjpf " $temp_dir / ${ archive } " -C " $temp_dir " " ${ repository } "
# Send it over
verbose_echo "Copying repository archive to remote host."
scp -P ${ target_port } " $temp_dir / ${ archive } " " ${ target_user } @ ${ target_host } : \" ${ target_dir } / ${ archive } \" "
done
verbose_echo "Cleaning up."
rm -Rf $temp_dir
IFS = " $ifs_original "
# End
verbose_echo " ${ cmdname } completed at ` date ` ."
exit $EX_OK