224 lines
9.2 KiB
Bash
Executable file
224 lines
9.2 KiB
Bash
Executable file
#!/bin/bash
|
|
#set -x
|
|
|
|
# get path to all needed tools
|
|
# /bin
|
|
cp=$(which cp)
|
|
date=$(which date)
|
|
echo=$(which echo)
|
|
grep=$(which grep)
|
|
mktemp=$(which mktemp)
|
|
mv=$(which mv)
|
|
pwd=$(which pwd)
|
|
rm=$(which rm)
|
|
sed=$(which sed)
|
|
tar=$(which tar)
|
|
umount=$(which umount)
|
|
# /usr/bin
|
|
cut=$(which cut)
|
|
dirname=$(which dirname)
|
|
expr=$(which expr)
|
|
head=$(which head)
|
|
nice=$(which nice)
|
|
rsync=$(which rsync)
|
|
seq=$(which seq)
|
|
ssh=$(which ssh)
|
|
sshfs=$(which sshfs)
|
|
tail=$(which tail)
|
|
|
|
# check if all needed tools are installed (only the ones not installed under /bin/)
|
|
alltoolsinstalled="yes"
|
|
test "$cut" = "" && echo "'cut' not installed or not found by 'which'" && alltoolsinstalled="no"
|
|
test "$dirname" = "" && echo "'dirname' not installed or not found by 'which'" && alltoolsinstalled="no"
|
|
test "$expr" = "" && echo "'expr' not installed or not found by 'which'" && alltoolsinstalled="no"
|
|
test "$head" = "" && echo "'head' not installed or not found by 'which'" && alltoolsinstalled="no"
|
|
test "$nice" = "" && echo "'nice' not installed or not found by 'which'" && alltoolsinstalled="no"
|
|
test "$rsync" = "" && echo "'rsync' not installed or not found by 'which'" && alltoolsinstalled="no"
|
|
test "$seq" = "" && echo "'sed' not installed or not found by 'which'" && alltoolsinstalled="no"
|
|
test "$ssh" = "" && echo "'ssh' not installed or not found by 'which'" && alltoolsinstalled="no"
|
|
test "$sshfs" = "" && echo "'sshfs' not installed or not found by 'which'" && alltoolsinstalled="no"
|
|
test "$tail" = "" && echo "'tail' not installed or not found by 'which'" && alltoolsinstalled="no"
|
|
|
|
if [ "$alltoolsinstalled" = "no" ]
|
|
then
|
|
exit 1
|
|
fi
|
|
|
|
# main configuration
|
|
script_dir="$( cd "$( $dirname "${BASH_SOURCE[0]}" )" && $pwd )"
|
|
config_file="$script_dir/main.cfg"
|
|
# timestamps yyyy-mm-dd and unixtime for calculating
|
|
backup_stamp=$($date +%F)
|
|
backup_time=$($date -d$backup_stamp +%s)
|
|
# check if it is the first of the month to do monthly backups
|
|
backup_month="no"
|
|
if [ "$($echo $backup_stamp | $cut -d- -f3)" = "01" ]
|
|
then
|
|
backup_month="yes"
|
|
fi
|
|
|
|
# source a specified section from a specified config
|
|
function source_section {
|
|
config_name="$1"
|
|
section_name="$2"
|
|
section_start="^\[$section_name\]$"
|
|
section_end="^\[/$section_name\]$"
|
|
|
|
line_start=$($grep -n "$section_start" "$config_name" | $cut -d: -f1)
|
|
line_end=$($expr $($grep -n "$section_end" "$config_name" | $cut -d: -f1) - 1)
|
|
line_diff=$($expr $line_end - $line_start)
|
|
|
|
tmp_file=$($mktemp)
|
|
$head -n $line_end "$config_name" | $tail -n $line_diff > "$tmp_file"
|
|
source "$tmp_file"
|
|
$rm -f "$tmp_file"
|
|
}
|
|
|
|
# copy file with rsync to server and save last timestamp to logfile
|
|
function rsync_server {
|
|
filefrom="$1"
|
|
dirto="$2"
|
|
logfileentry="$3"
|
|
#nice -n 19 rsync -rle "ssh -i $keyfile" "$filefrom" "$userserver:$dirto"
|
|
# limit the bandwith
|
|
$nice -n 19 $rsync --bwlimit=100000 -rle "$ssh -i $keyfile" "$filefrom" "$userserver:$dirto"
|
|
ret=$?
|
|
if [ $ret -ne 0 ]
|
|
then
|
|
$echo "problem in rsync: $filefrom"
|
|
fi
|
|
$echo "$filefrom" | $grep ".month." > /dev/null 2>&1
|
|
ret2=$?
|
|
# on monthly backups and connection errors there should be no update of logfile
|
|
if [ $ret2 -ne 0 -a $ret -eq 0 ]
|
|
then
|
|
$sed -e "s/^$logfileentry .*$/${logfileentry} $backup_time/" "$logfile" > "$logfile.tmp"
|
|
$mv -f "$logfile.tmp" "$logfile"
|
|
fi
|
|
}
|
|
|
|
# general section from main config
|
|
source_section "$config_file" "general"
|
|
|
|
# handle all specified configs
|
|
for config_single in $configs
|
|
do
|
|
# does the configuration file exists?
|
|
config_act="$confdir/$config_single"
|
|
if [ -e "$config_act" ]
|
|
then
|
|
# general section from specific config
|
|
source_section "$config_act" "general"
|
|
# change folder for backup
|
|
pushd "$rootdir" > /dev/null
|
|
# handle all specified folders
|
|
for dir_single in $dirssingle
|
|
do
|
|
# check if folder exists
|
|
if [ -e "$dir_single" ]
|
|
then
|
|
# section for specified folder
|
|
source_section "$config_act" "$dir_single"
|
|
# rotate is done through days, so we have to know the interval in sections
|
|
rotate_stamp=$($expr $time \* 24 \* 60 \* 60)
|
|
# for new configurations that does not have a last timestamp we create a zero one
|
|
$grep "^${config_single}_$dir_single " $logfile > /dev/null 2>&1
|
|
if [ $? -ne 0 ]
|
|
then
|
|
$echo "${config_single}_$dir_single 0" >> $logfile
|
|
fi
|
|
# add /. to directory for also backing up softlinks
|
|
dir_single_soft_link_path="$dir_single/."
|
|
# get the stamp for the last backup
|
|
last_stamp=$($grep "^${config_single}_$dir_single " $logfile | $cut -d" " -f2)
|
|
# get the stamp for the next backup
|
|
now_stamp=$($expr $last_stamp + $rotate_stamp)
|
|
do_backup="no"
|
|
do_monthly="no"
|
|
do_normal="no"
|
|
# check wether it is time to do a backup by time and also month
|
|
if [ $now_stamp -le $backup_time ]
|
|
then
|
|
do_backup="yes"
|
|
if [ "$rotate" != "inc" ]
|
|
then
|
|
do_normal="yes"
|
|
fi
|
|
fi
|
|
if [ "$backup_month" = "yes" -a "$monthly" = "yes" ]
|
|
then
|
|
do_backup="yes"
|
|
do_monthly="yes"
|
|
fi
|
|
# now we are sure to do a backup
|
|
if [ "$do_backup" = "yes" ]
|
|
then
|
|
# we want an incremental backup since last one
|
|
if [ "$rotate" = "inc" ]
|
|
then
|
|
# tar is not able to handle unix-timestamps, so we calculate the required one
|
|
tar_stamp=$($date -d "1970-01-01 $last_stamp sec" +%F)
|
|
# only changed files since last modification in backup
|
|
if [ -f "$dir_single_soft_link_path/backup.ignore" ]
|
|
then
|
|
$nice -n 19 $tar czf "$dir_single.$backup_stamp.tar.gz" --warning=none --exclude-from="$dir_single_soft_link_path/backup.ignore" -N "$tar_stamp" "$dir_single_soft_link_path"
|
|
else
|
|
$nice -n 19 $tar czf "$dir_single.$backup_stamp.tar.gz" --warning=none -N "$tar_stamp" "$dir_single_soft_link_path"
|
|
fi
|
|
rsync_server "$dir_single.$backup_stamp.tar.gz" "$backupdir/$backupdirsingle/" "${config_single}_$dir_single"
|
|
# delete backups from local
|
|
$rm -f "$dir_single.$backup_stamp.tar.gz"
|
|
fi # if [ "$rotate" = "inc" ]
|
|
# we want a full backup
|
|
if [ "$do_monthly" = "yes" -o "$do_normal" = "yes" ]
|
|
then
|
|
# backup everything
|
|
if [ -f "$dir_single_soft_link_path/backup.ignore" ]
|
|
then
|
|
$nice -n 19 $tar czf "$dir_single.tar.gz" --warning=none --exclude-from="$dir_single_soft_link_path/backup.ignore" "$dir_single_soft_link_path"
|
|
else
|
|
$nice -n 19 $tar czf "$dir_single.tar.gz" --warning=none "$dir_single_soft_link_path"
|
|
fi
|
|
# check wether we should rotate
|
|
if [ "$rotate" != "inc" -a "$do_normal" = "yes" ]
|
|
then
|
|
|
|
# mount for renaming
|
|
$sshfs $userserver:$backupdir $backupdir_local -o IdentityFile=$keyfile -o IdentitiesOnly=yes
|
|
|
|
# rotate old backups
|
|
for count in `seq $rotate -1 2`
|
|
do
|
|
count_last=$(expr $count - 1)
|
|
$rm -f "$backupdir_local/$backupdirsingle/$dir_single.tar.gz.$count"
|
|
$mv -f "$backupdir_local/$backupdirsingle/$dir_single.tar.gz.$count_last" "$backupdir_local/$backupdirsingle/$dir_single.tar.gz.$count" > /dev/null 2>&1
|
|
done
|
|
$rm -f "$backupdir_local/$backupdirsingle/$dir_single.tar.gz.1"
|
|
$mv -f "$backupdir_local/$backupdirsingle/$dir_single.tar.gz" "$backupdir_local/$backupdirsingle/$dir_single.tar.gz.1" > /dev/null 2>&1
|
|
|
|
# unmount
|
|
$umount $backupdir_local
|
|
|
|
fi # if [ "$rotate" != "inc" -a "$do_normal" = "yes" ]
|
|
# copy new backups
|
|
if [ "$do_normal" = "yes" ]
|
|
then
|
|
rsync_server "$dir_single.tar.gz" "$backupdir/$backupdirsingle/" "${config_single}_$dir_single"
|
|
fi
|
|
if [ "$do_monthly" = "yes" ]
|
|
then
|
|
#TODO: check why move sometimes causes problems
|
|
$nice -n 19 $cp "$dir_single.tar.gz" "$dir_single.$backup_stamp.month.tar.gz"
|
|
rsync_server "$dir_single.$backup_stamp.month.tar.gz" "$backupdir/$backupdirsingle/" "${config_single}_$dir_single"
|
|
fi
|
|
# delete backups from local
|
|
$rm -f "$dir_single.$backup_stamp.month.tar.gz"
|
|
$rm -f "$dir_single.tar.gz"
|
|
fi # if [ "$do_monthly" = "yes" -o "$do_normal" = "yes" ]
|
|
fi # if [ "$do_backup" = "yes" ]
|
|
fi # if [ -e "$dir_single" ]
|
|
done # for dir_single in $dirssingle
|
|
# go back
|
|
popd > /dev/null
|
|
fi # if [ -e "$config_act" ]
|
|
done # for config_single in $configs
|