From e848de475ed73d71050980a6d3b3b59271c53344 Mon Sep 17 00:00:00 2001 From: lookshe Date: Thu, 11 Sep 2014 10:38:13 +0200 Subject: initial commit --- README.md | 1 + backup.sh | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.cfg | 9 ++++ system.cfg | 15 ++++++ user.cfg | 23 +++++++++ www.cfg | 17 +++++++ 6 files changed, 233 insertions(+) create mode 100644 README.md create mode 100755 backup.sh create mode 100644 main.cfg create mode 100644 system.cfg create mode 100644 user.cfg create mode 100644 www.cfg diff --git a/README.md b/README.md new file mode 100644 index 0000000..0f20abe --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +configurable backup-script for bash diff --git a/backup.sh b/backup.sh new file mode 100755 index 0000000..95d836c --- /dev/null +++ b/backup.sh @@ -0,0 +1,168 @@ +#!/bin/bash +#set -x + +# 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) + + head -n $line_end "$config_name" | tail -n $line_diff > /tmp/backup.tmp + source /tmp/backup.tmp + rm -f /tmp/backup.tmp +} + +# 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" "$1" "$userserver:$dirto" + # limit the bandwith + nice -n 19 rsync --bwlimit=100000 -rle "ssh -i $keyfile" "$1" "$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 -ne 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 + # 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 + nice -n 19 tar czf "$dir_single.$backup_stamp.tar.gz" --warning=none -N "$tar_stamp" "$dir_single" + 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 + nice -n 19 tar czf "$dir_single.tar.gz" --warning=none "$dir_single" + # 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 diff --git a/main.cfg b/main.cfg new file mode 100644 index 0000000..f12cbb2 --- /dev/null +++ b/main.cfg @@ -0,0 +1,9 @@ +[general] +confdir=/PATH/TO/THE/CONFIGUGATION/FILES +configs="user.cfg www.cfg system.cfg" +backupdir=/BASE/PATH/ON/THE/BACKUP/SERVER +backupdir_local=/LOCAL/PATH/TO/MOUNT/POINT +logfile=$confdir/logfile.log +keyfile=/PATH/TO/KEYFILE/id_rsa +userserver="backupuser@backup.server" +[/general] diff --git a/system.cfg b/system.cfg new file mode 100644 index 0000000..1986dce --- /dev/null +++ b/system.cfg @@ -0,0 +1,15 @@ +[general] +rootdir=/ +dirssingle="root etc" +backupdirsingle=system +[/general] +[root] +rotate=10 +time=1 +monthly=yes +[/root] +[etc] +rotate=30 +time=1 +monthly=yes +[/etc] diff --git a/user.cfg b/user.cfg new file mode 100644 index 0000000..5dcc22e --- /dev/null +++ b/user.cfg @@ -0,0 +1,23 @@ +[general] +rootdir=/home +dirssingle="user1 user2 user3" +backupdirsingle=users +[/general] +[user1] +#daily backup with 3 old versions +rotate=3 +time=1 +monthly=no +[/user1] +[user2] +#daily incremental backup +rotate=inc +time=1 +monthly=no +[/user2] +[user3] +#weekly backup with 3 old versions +rotate=3 +time=7 +monthly=no +[/user3] diff --git a/www.cfg b/www.cfg new file mode 100644 index 0000000..bc272f1 --- /dev/null +++ b/www.cfg @@ -0,0 +1,17 @@ +[general] +rootdir=/var/www +dirssingle="domain.tld example.com" +backupdirsingle=www +[/general] +[domain.tld] +#daily incremental backup with monthly snapshots +rotate=inc +time=1 +monthly=yes +[/domain.tld] +[example.com] +#backup every third day and hold 5 old versions +rotate=5 +time=3 +monthly=no +[/example.com] -- cgit v1.2.3