[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: Shell script to make or restore backups of repositories

From: Martijn Ras <Martijn.Ras_at_GMail.com>
Date: Wed, 12 Aug 2009 20:04:17 +0200

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Heya Folks,

I've updated my script to remove a couple of unnecessary GNU/Bash-isms
as Tony pointed out.

In case you run into problems let me know which shell and operating system you use.

Mazzel,

Martijn.

#!/bin/sh
#
# ------------------------------------------------------------------------
#
# Copyright (C) 2007 Martijn Ras
#
# ------------------------------------------------------------------------
#
# 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 2 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, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ------------------------------------------------------------------------
#
#

#
# Set the following variables if you do not want to specify them on the command line.
#

#
# All repositories under this directory will be backed up.
#
#ROOTDIRECTORY=''

#
# All backups will be written into this directory (defaults to a mktemp generated directory).
#
#BACKUPDIRECTORY=''

#
# The default subcommand to be performed (defaults to 'help', except when run from a cron directory where it defaults to 'full').
#
#SUBCOMMAND=''

#
# The name of the user and group to be set as the owner of the backups.
# This might be necessary to have the items packed up by an archiving tool.
#
#BACKUPDIRECTORYUSER=''
#BACKUPDIRECTORYGROUP="${BACKUPDIRECTORYUSER}"

#
# The name of the user and group to be set as the owner of the repositories.
# When run as root in a cron job it might be necessary to reset the ownership.
#
#SUBVERSIONDIRECTORYUSER=''
#SUBVERSIONDIRECTORYGROUP="${SUBVERSIONDIRECTORYUSER}"

#
# check_commands ()
#
# Checks the existence of the specified commands.
#
# Parameters:
# @) A space separated list of all commands of which to check the existence.
#
function check_commands () {
        for COMMAND in "$@"
        do
                execute_command "which '${COMMAND}'" "Cannot find: ${COMMAND}!"
        done
}

#
# error ()
#
# Print the specified error message and exit the program.
#
# Parameters:
# 1) The error message to print before exiting the program.
#
function error () {
        echo -e "\nERROR:\n\n$1\n" 2> /dev/null
        remove_tempfile
        exit 1
}

#
# execute_command ()
#
# Execute a command and print an error message if needs be.
#
# Parameters:
# 1) The command to execute.
# 2) The error message to print if needs be.
#
function execute_command () {
        sh -c "$1" > /dev/null 2>&1
        if test $? -ne 0
        then
                error "$2"
        fi
}

#
# make_directories ()
#
# Make the directories specified.
#
# Parameters:
# 1) An array with the directories to make.
#
function make_directories () {
        for DIRECTORY in "$@"
        do
                if ! test -d "${DIRECTORY}"
                then
                        execute_command "mkdir -p '${DIRECTORY}'" "Failed to make directory: ${DIRECTORY}!"
                fi
        done
}

#
# processsubcommand ()
#
# Works out which subcommand was specified on the command line or sets the default.
#
# Parameters:
# 1) The subcommand specified on the command line.
#
function processsubcommand () {
        if test "$1" = 'full' -o "$1" = 'f'
        then
                SUBCOMMAND='full'
        elif test "$1" = 'help' -o "$1" = 'h' -o "$1" = '?'
        then
                SUBCOMMAND='help'
        elif test "$1" = 'incremental' -o "$1" = 'i' -o "$1" = 'incr'
        then
                SUBCOMMAND='incremental'
        elif test "$1" = 'list' -o "$1" = 'l' -o "$1" = 'ls'
        then
                SUBCOMMAND='list'
        elif test "$1" = 'restore' -o "$1" = 'r' -o "$1" = 'rest'
        then
                SUBCOMMAND='restore'
        else
                if test "`echo "$0" | sed 's#\(/etc/cron\).*#\1#'`" == '/etc/cron'
                then
                        SUBCOMMAND='full'
                elif test -z "${SUBCOMMAND}"
                then
                        SUBCOMMAND='help'
                fi
        fi
}
#
# processsubcommandparameters ()
#
# Works out which parameters have been specified for the subcommand.
#
# Parameters:
# *) Depended on the subcommand specified.
#
function processsubcommandparameters () {
        if test "${SUBCOMMAND}" = 'full' -o "${SUBCOMMAND}" = 'incremental'
        then
                if test -n "$2"
                then
                        ROOTDIRECTORY="$1"
                        BACKUPDIRECTORY="$2"
                elif test -n "$1"
                then
                        ROOTDIRECTORY="$1"
                fi
                if test -z "${BACKUPDIRECTORY}"
                then
                        BACKUPDIRECTORY="`mktemp -d`"
                        if test $? -ne 0
                        then
                                error "Failed to create temporary directory for backup!"
                        fi
                fi
                make_directories "${BACKUPDIRECTORY}"
        elif test "${SUBCOMMAND}" = 'help'
        then
                SUBCOMMAND="$1"
                usage
        elif test "${SUBCOMMAND}" = 'list'
        then
                ROOTDIRECTORY="$1"
        elif test "${SUBCOMMAND}" = 'restore'
        then
                if test -n "$2"
                then
                        ROOTDIRECTORY="$1"
                        BACKUPFILE="$2"
                elif test -n "$1"
                then
                        BACKUPFILE="$1"
                fi
        fi
}

#
# processparameters ()
#
# Processes all parameters specified on the command line.
#
# Parameters:
# @) The parameters specified on the command line.
#
function processparameters () {
        processsubcommand "$@"
        shift
        processsubcommandparameters "$@"
}

#
# remove_tempfile ()
#
# Remove a temporary file used by the program.
#
# Parameters:
# None
#
function remove_tempfile () {
        if test -n "${TEMPFILE}" -a -f "${TEMPFILE}"
        then
                execute_command "rm '${TEMPFILE}'" "\nERROR:\n\nFailed to remove temporary file: ${TEMPFILE}!"
        fi
}

#
# tempfile ()
#
# Create a new temporary file for use by the program.
#
# Parameters:
# None
#
function tempfile () {
        TEMPFILE="`mktemp -q -t 2> /dev/null`"
        if test $? -ne 0
        then
                error "Failed to create temporary file!"
        fi
}

#
# usage ()
#
# Prints the usage information.
#
function usage () {
        echo 'usage:'
        echo ''
        if test "${SUBCOMMAND}" = 'full' -o "${SUBCOMMAND}" = 'f'
        then
                echo ' SubversionBackup f <subversionroot> <backupdirectory>'
                echo ' SubversionBackup full <subversionroot> <backupdirectory>'
                echo ''
                echo 'SubversionBackup will create full backups of all repositories under subversionroot in the backupdirectory.'
        elif test "${SUBCOMMAND}" = 'incremental' -o "${SUBCOMMAND}" = 'i' -o "${SUBCOMMAND}" = 'incr'
        then
                echo ' SubversionBackup i <subversionroot> <backupdirectory>'
                echo ' SubversionBackup incr <subversionroot> <backupdirectory>'
                echo ' SubversionBackup incremental <subversionroot> <backupdirectory>'
                echo ''
                echo 'SubversionBackup will create incremental backups of all repositories under the subversionroot in the backupdirectory.'
        elif test "${SUBCOMMAND}" = 'list' -o "${SUBCOMMAND}" = 'l' -o "${SUBCOMMAND}" = 'ls'
        then
                echo ' SubversionBackup l <subversionroot>'
                echo ' SubversionBackup ls <subversionroot>'
                echo ' SubversionBackup list <subversionroot>'
                echo ''
                echo 'SubversionBackup will list all repositories under the subversionroot.'
        elif test "${SUBCOMMAND}" = 'restore' -o "${SUBCOMMAND}" = 'r' -o "${SUBCOMMAND}" = 'rest'
        then
                echo ' SubversionBackup r <subversionroot> <backup>'
                echo ' SubversionBackup rest <subversionroot> <backup>'
                echo ' SubversionBackup restore <subversionroot> <backup>'
                echo ''
                echo 'Restores a backup, created by svnadmin dump, of a subversion repository under the subversionroot.'
        else
                echo ' SubversionBackup [subcommand] <subversionroot> [<backupdirectory>|<backup>]'
                echo ''
                echo 'Type "SubversionBackup help <subcommand>" for help on a specific subcommand.'
                echo ''
                echo 'SubversionBackup will either create backups of all repositories under the subversionroot in the backupdirectory or restore a backup in the subversionroot.'
                echo ''
                echo 'Available subcommands:'
                echo ' full (f)'
                echo ' help (h, ?)'
                echo ' incremental (i, incr)'
                echo ' list (l, ls)'
                echo ' restore (r, rest)'
        fi
        echo ''
        exit
}

check_commands 'basename' 'bzip2' 'chown' 'date' 'dirname' 'find' 'head' 'ls' 'mkdir' 'mktemp' 'sed' 'sort' 'svnadmin' 'svnlook' 'wc' 'which'

processparameters "$@"

START="`date +%s`"
if test $? -ne 0
then
        START=''
fi

execute_command "umask 077" "Failed to set umask!"

if test "`echo "${ROOTDIRECTORY}" | sed 's#.*\(.\)$#\1#'`" != '/'
then
        ROOTDIRECTORY="${ROOTDIRECTORY}/"
fi

if test "${SUBCOMMAND}" = 'restore'
then
        REPOSITORY="${ROOTDIRECTORY}`basename "${BACKUPFILE}" | sed 's#^\(.*\)\.backup\.[0-9]*-[0-9]*#\1#'`"
        if test $? -ne 0
        then
                error "Failed to determine repository to restore!"
        fi
        echo "Restoring repository: ${BACKUPFILE} under ${REPOSITORY}"
        make_directories "`dirname "${REPOSITORY}"`"
        execute_command "svnadmin create '${REPOSITORY}'" "Failed to create repository ${REPOSITORY}!"
        execute_command "bzip2 -dc '${BACKUPFILE}' | svnadmin load '${REPOSITORY}'" "Failed to load backup (${BACKUPFILE}) into repository ${REPOSITORY}!"
else
        if test -d "${ROOTDIRECTORY}"
        then
                cd "${ROOTDIRECTORY}"
        else
                echo 'Invalid default or specified subversionroot:'
                echo ''
                echo " ${ROOTDIRECTORY}"
                echo ''
                exit 1
        fi
        if test "${SUBCOMMAND}" = 'list'
        then
                echo 'SubversionBackup will create backups of the following repositories:'
                echo ''
        fi
        for REPOSITORY in `find . -maxdepth 1 -mindepth 1 -type d | sed 's#\./##'`
        do
                if test -d "${REPOSITORY}" -a -f "${REPOSITORY}/format"
                then
                        if test "${SUBCOMMAND}" = 'list'
                        then
                                echo " ${ROOTDIRECTORY}${REPOSITORY}"
                        else
                                echo "Starting ${SUBCOMMAND} backup of repository:"
                                echo -n " ${ROOTDIRECTORY}${REPOSITORY}"
                                LAST='0'
                                if test "${SUBCOMMAND}" = 'incremental'
                                then
                                        LAST="`ls ${BACKUPDIRECTORY}/${REPOSITORY}.backup.* 2>/dev/null | sort -r | head -1 | sed 's#.*\.backup\.[0-9]*-\([0-9]*\).*#\1#'`"
                                        if test "${LAST}" = ''
                                        then
                                                LAST='0'
                                        fi
                                fi
                                HEAD="`svnlook youngest "${REPOSITORY}"`"
                                if test $? -ne 0
                                then
                                        error "Failed to determine youngest revision of repository ${REPOSITORY}!"
                                fi
                                if test ${LAST} -lt ${HEAD}
                                then
                                        COMMAND="svnadmin dump --quiet"
                                        if test "${SUBCOMMAND}" = 'incremental'
                                        then
                                                COMMAND="${COMMAND} --${SUBCOMMAND}"
                                        fi
                                        COMMAND="${COMMAND} --revision ${LAST}:${HEAD} ${REPOSITORY}"
                                        ${COMMAND} | bzip2 > "${BACKUPDIRECTORY}/${REPOSITORY}.backup.${LAST}-${HEAD}"
                                        if test $? -eq 0
                                        then
                                                echo ' - SUCCEEDED'
                                        else
                                                echo " - FAILED: range (${LAST}:${HEAD})"
                                        fi
                                elif test ${LAST} -gt ${HEAD}
                                then
                                        echo " - ERROR: Invalid range (${LAST}:${HEAD})"
                                else
                                        echo " - WARNING: Skipping ${SUBCOMMAND} backup of repository ${REPOSITORY} (${LAST}:${HEAD})"
                                fi
                        fi
                else
                        if test "${SUBCOMMAND}" != 'list'
                        then
                                echo "Not a subversion repository: ${ROOTDIRECTORY}${REPOSITORY}" 1>&2
                        fi
                fi
        done
fi
if test "${SUBCOMMAND}" != 'list'
then
        if test -n "${SUBVERSIONDIRECTORYUSER}"
        then
                echo "Setting ownership of repositories to ${SUBVERSIONDIRECTORYUSER}:${SUBVERSIONDIRECTORYGROUP}"
                execute_command "chown -R ${SUBVERSIONDIRECTORYUSER}:${SUBVERSIONDIRECTORYGROUP} '${ROOTDIRECTORY}'" "Failed to set ownership of repositories to ${SUBVERSIONDIRECTORYUSER}:${SUBVERSIONDIRECTORYGROUP}"
        fi
        if test -n "${BACKUPDIRECTORYUSER}" -a "${SUBCOMMAND}" != 'restore'
        then
                echo ''
                echo "Setting ownership of backups of repositories to ${BACKUPDIRECTORYUSER}:${BACKUPDIRECTORYGROUP}"
                execute_command "chown -R ${BACKUPDIRECTORYUSER}:${BACKUPDIRECTORYGROUP} '${BACKUPDIRECTORY}'" "Failed to set ownership of backups of repositories to ${BACKUPDIRECTORYUSER}:${BACKUPDIRECTORYGROUP}"
        fi
        if test "${START}" != ''
        then
                echo ''
                END="`date +%s`"
                echo "SubversionBackup completed in $((${END} - ${START})) seconds"
        fi
fi
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

iQEVAwUBSoMEIft+Km8vKaO1AQJ2TwgAj4klohCWD2AHsoXeHF9qpPQ6vw9yVu/G
OeeNYRLFvOBAK3O3hNiMkqWVv9kvai90hFMJq7izh7rnWrcYMPpAbMm0WqJeE92H
eb6YHH6uBoebXhSBOie/da4ir/XBmVd4H9ljLJKYZjhrUyMle7HD++RyidOjgaBd
jrF80LI3C9vrygW51QlSs24S484reFWwd70UqBfu8w63kb7zNkgTK1Bn+OV/UJIe
z7t0M7eSjDJD2Pyc2K/Qm1U6PX3oRLXxz/0LwZfZBbAyWYhuhwuW/j1xg2AU9B8Q
DcBvnPMqf4gc4npZeDnPUcf8skzGq6wq1b4fR/UYBViPr97BP8haaw==
=D5ZU
-----END PGP SIGNATURE-----

------------------------------------------------------
http://subversion.tigris.org/ds/viewMessage.do?dsForumId=1065&dsMessageId=2382968

To unsubscribe from this discussion, e-mail: [users-unsubscribe_at_subversion.tigris.org].
Received on 2009-08-12 20:08:37 CEST

This is an archived mail posted to the Subversion Users mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.