commit e848de475ed73d71050980a6d3b3b59271c53344
Author: lookshe <github@lookshe.org>
Date:   Thu Sep 11 10:38:13 2014 +0200

    initial commit

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]