mirror of
https://0xacab.org/liberate/backupninja.git
synced 2024-09-20 07:31:41 +02:00
78884142e7
The modelines added match the emacs lines already present and also set the filetype to sh (just like the emacs lines).
259 lines
7.2 KiB
Bash
259 lines
7.2 KiB
Bash
# -*- mode: sh; sh-basic-offset: 3; indent-tabs-mode: nil; -*-
|
|
# vim: set filetype=sh sw=3 sts=3 expandtab autoindent:
|
|
#
|
|
# rdiff-backup handler script for backupninja
|
|
# requires rdiff-backup
|
|
#
|
|
|
|
### FUNCTIONS ###
|
|
|
|
function test_connection() {
|
|
# given a user and host,
|
|
# tests the connection.
|
|
# if user or host is missing, returns 0
|
|
# (ie, assume it's a local connection).
|
|
if [ $# -lt 2 ]; then
|
|
debug "(local is assumed to be a good connection)"
|
|
return 0
|
|
fi
|
|
local user=$1
|
|
local host=$2
|
|
debug "ssh $sshoptions -o PasswordAuthentication=no $host -l $user 'echo -n 1'"
|
|
local ret=`ssh $sshoptions -o PasswordAuthentication=no $host -l $user 'echo -n host is alive'`
|
|
if echo $ret | grep "host is alive"; then
|
|
debug "Connected to $host as $user successfully"
|
|
else
|
|
fatal "Can't connect to $host as $user."
|
|
fi
|
|
}
|
|
|
|
function get_version() {
|
|
# given no arguments, returns the local version.
|
|
# given a user and host, returns the remote version.
|
|
# if user or host is missing, returns the local version.
|
|
if [ "$#" -lt 2 ]; then
|
|
debug "$RDIFFBACKUP -V"
|
|
echo `$RDIFFBACKUP -V`
|
|
else
|
|
local user=$1
|
|
local host=$2
|
|
debug "ssh $sshoptions $host -l $user '$RDIFFBACKUP -V'"
|
|
echo `ssh $sshoptions $host -l $user "$RDIFFBACKUP -V | grep rdiff-backup"`
|
|
fi
|
|
}
|
|
|
|
function check_consistency() {
|
|
local section=$1
|
|
local type=$2
|
|
local user=$3
|
|
local host=$4
|
|
if [ "$type" == "local" ]; then
|
|
if [ "$user" != "" ]; then
|
|
warning "User should not be specified for local $section."
|
|
fi
|
|
if [ "$host" != "" ]; then
|
|
warning "Host should not be specified for local $section."
|
|
fi
|
|
fi
|
|
if [ "$type" == "remote" ]; then
|
|
if [ "$user" == "" ]; then
|
|
fatal "User must be specified for remote $section."
|
|
fi
|
|
if [ "host" == "" ]; then
|
|
fatal "Host must be specifed for remote $section."
|
|
fi
|
|
fi
|
|
}
|
|
|
|
function check_cstream() {
|
|
local cstream=$1
|
|
if [ ! -x $cstream ]; then
|
|
fatal "Can't find your cstream binary (trying: $cstream). If you use bwlimit you must have cstream installed."
|
|
fi
|
|
}
|
|
|
|
### GET CONFIG ###
|
|
|
|
getconf options
|
|
getconf testconnect yes
|
|
getconf nicelevel 0
|
|
getconf bwlimit
|
|
getconf ignore_version no
|
|
|
|
setsection source
|
|
getconf type; sourcetype=$type
|
|
getconf user; sourceuser=$user
|
|
getconf host; sourcehost=$host
|
|
check_consistency "source" "$type" "$user" "$host"
|
|
getconf label
|
|
getconf keep 60
|
|
getconf include
|
|
getconf vsnames all
|
|
getconf vsinclude
|
|
getconf exclude
|
|
|
|
setsection dest
|
|
getconf directory; destdir=$directory
|
|
# strip trailing /
|
|
destdir=${destdir%/}
|
|
getconf type; desttype=$type
|
|
getconf user; destuser=$user
|
|
getconf host; desthost=$host
|
|
getconf sshoptions
|
|
check_consistency "destination" "$type" "$user" "$host"
|
|
|
|
if [ -n "$sshoptions" ] && echo $options | grep -qv "remote-schema"; then
|
|
options="$options --remote-schema 'ssh -C $sshoptions %s rdiff-backup --server'"
|
|
fi
|
|
|
|
### CHECK CONFIG ###
|
|
|
|
# If vservers are configured, check that the ones listed in $vsnames do exist.
|
|
local usevserver=no
|
|
if [ $vservers_are_available = yes ]; then
|
|
if [ "$vsnames" = all ]; then
|
|
vsnames="$found_vservers"
|
|
else
|
|
if ! vservers_exist "$vsnames" ; then
|
|
fatal "At least one of the vservers listed in vsnames ($vsnames) does not exist."
|
|
fi
|
|
fi
|
|
if [ -n "$vsinclude" ]; then
|
|
info "Using vservers '$vsnames'"
|
|
usevserver=yes
|
|
fi
|
|
else
|
|
[ -z "$vsinclude" ] || warning 'vservers support disabled in backupninja.conf, vsincludes configuration lines will be ignored'
|
|
fi
|
|
|
|
# check the connection at the source and destination
|
|
[ -n "$test" ] || test=0
|
|
if [ "$testconnect" = "yes" ] || [ "${test}" -eq 1 ]; then
|
|
test_connection $sourceuser $sourcehost
|
|
test_connection $destuser $desthost
|
|
fi
|
|
|
|
if [ "$ignore_version" != "yes" ]; then
|
|
# see that rdiff-backup has the same version at the source and destination
|
|
sourceversion=`get_version $sourceuser $sourcehost`
|
|
destversion=`get_version $destuser $desthost`
|
|
if [ "$sourceversion" != "$destversion" ]; then
|
|
fatal "rdiff-backup does not have the same version at the source and at the destination."
|
|
fi
|
|
fi
|
|
|
|
# source specific checks
|
|
case $sourcetype in
|
|
remote ) execstr_sourcepart="$sourceuser@$sourcehost::/" ;;
|
|
local ) execstr_sourcepart="/" ;;
|
|
* ) fatal "sourcetype '$sourcetype' is neither local nor remote" ;;
|
|
esac
|
|
|
|
# destination specific checks
|
|
[ "$destdir" != "" ] || fatal "Destination directory not set"
|
|
case $desttype in
|
|
remote ) execstr_destpart="$destuser@$desthost::$destdir/$label" ;;
|
|
local ) execstr_destpart="$destdir/$label" ;;
|
|
* ) fatal "desttype '$desttype' is neither local nor remote" ;;
|
|
esac
|
|
|
|
### REMOVE OLD BACKUPS ###
|
|
|
|
if [ "$keep" != yes ]; then
|
|
|
|
if [ "`echo $keep | tr -d 0-9`" == "" ]; then
|
|
# add D if no other date unit is specified
|
|
keep="${keep}D"
|
|
fi
|
|
|
|
removestr="$RDIFFBACKUP $options --force --remove-older-than $keep "
|
|
if [ "$desttype" == "remote" ]; then
|
|
removestr="${removestr}${destuser}@${desthost}::"
|
|
fi
|
|
removestr="${removestr}${destdir}/${label}";
|
|
|
|
debug "$removestr"
|
|
if [ $test = 0 ]; then
|
|
output="`su -c "$removestr" 2>&1`"
|
|
if [ $? = 0 ]; then
|
|
debug $output
|
|
info "Removing backups older than $keep days succeeded."
|
|
else
|
|
warning $output
|
|
warning "Failed removing backups older than $keep."
|
|
fi
|
|
fi
|
|
|
|
fi
|
|
|
|
# Add cstream
|
|
|
|
if [ ! -z $bwlimit ]; then
|
|
check_cstream $CSTREAM;
|
|
if [ "$desttype" = "remote" ]; then
|
|
RDIFFBACKUP="$RDIFFBACKUP --remote-schema 'cstream -t $bwlimit | ssh %s \''rdiff-backup --server\'''"
|
|
elif [ "$sourcetype" = "remote" ]; then
|
|
RDIFFBACKUP="$RDIFFBACKUP --remote-schema 'ssh %s \''rdiff-backup --server\'' | cstream -t $bwlimit'"
|
|
else
|
|
fatal "You specified a bandwidth limit but neither your source nor destination types are remote."
|
|
fi
|
|
fi
|
|
|
|
### EXECUTE ###
|
|
|
|
execstr="$RDIFFBACKUP $options --print-statistics "
|
|
|
|
set -o noglob
|
|
|
|
symlinks_warning="Maybe you have mixed symlinks and '*' in this statement, which is not supported."
|
|
|
|
# TODO: order the includes and excludes
|
|
# excludes
|
|
for i in $exclude; do
|
|
str="${i//__star__/*}"
|
|
execstr="${execstr}--exclude '$str' "
|
|
done
|
|
# includes
|
|
for i in $include; do
|
|
[ "$i" != "/" ] || fatal "Sorry, you cannot use 'include = /'"
|
|
str="${i//__star__/*}"
|
|
execstr="${execstr}--include '$str' "
|
|
done
|
|
|
|
# vsinclude
|
|
if [ $usevserver = yes ]; then
|
|
for vserver in $vsnames; do
|
|
for vi in $vsinclude; do
|
|
str="${vi//__star__/*}"
|
|
str="$VROOTDIR/$vserver$str"
|
|
if [ -n "$str" ]; then
|
|
execstr="${execstr}--include '$str' "
|
|
else
|
|
warning "vsinclude statement '${vi//__star__/*}' will be ignored for VServer $vserver. $symlinks_warning"
|
|
fi
|
|
done
|
|
done
|
|
fi
|
|
|
|
set +o noglob
|
|
|
|
# exclude everything else
|
|
[ "$include" != "" -o "$vsinclude" != "" ] && execstr="${execstr}--exclude '/*' "
|
|
|
|
# include client-part and server-part
|
|
execstr="${execstr}$execstr_sourcepart $execstr_destpart"
|
|
|
|
debug "$execstr"
|
|
if [ $test = 0 ]; then
|
|
output=`nice -n $nicelevel su -c "$execstr" 2>&1`
|
|
if [ $? = 0 ]; then
|
|
debug $output
|
|
info "Successfully finished backing up source $label"
|
|
else
|
|
warning $output
|
|
warning "Failed backup up source $label"
|
|
fi
|
|
fi
|
|
|
|
return 0
|