aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md1
-rwxr-xr-xbackup.sh168
-rw-r--r--main.cfg9
-rw-r--r--system.cfg15
-rw-r--r--user.cfg23
-rw-r--r--www.cfg17
6 files changed, 233 insertions, 0 deletions
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]