#!/bin/bash

### Konfiguration:
# Wovon soll ein Backup gemacht werden?
sourceDir='/';

# Wohin soll das Backup geschrieben werden?
backupDir='/data/backup';

# Was soll nicht im Backup sein? (Datei)
backupExludesFile='/root/bin/backup.exludes';

# Was soll dennoch im Backup sein? (Datei)
backupIncludesFile='/root/bin/backup.includes';

# Name des Backup. Wird Bestandteil des Dateinamens:
backupName='nightly';

# Wie viele allte Backups sollen behalten werden:
maxOldBackups=28;

# Dienste, die in der angegebenen Reihenfolge vor dem Backup anzuhalten sind:
servicesStopBevore=(mysql);

# Dienste, die in der angegebenen Teihenfolge nach dem Backup zu starten sind:
servicesStartAfter=(mysql);

### Wenn ab hier geändert wird, muss das Skript angepasst werden
YMD="$(date +%F)";

backupDateName="${YMD}-${backupName}";
backupRegex="^2[0-9]{3}-[0-9]{2}-[0-9]{2}-${backupName}$";

backupLogFile="${YMD}-${backupName}.log";
backupErrorLogFile="${YMD}-${backupName}.err.log";


if [ -d "${backupDir}" ]; then

    oldDir=$(pwd);
    cd ${backupDir};

    date > "${backupLogFile}";
    if [ -f "${backupLogFile}" ]; then

        date > "${backupErrorLogFile}";

        ### Löschen der alten Backups:
        countBackups=$(ls -d * | grep -P "${backupRegex}" | wc -l);
        if [ ${countBackups} -gt ${maxOldBackups} ]; then
            let newcounter=0;
            for dir in $(ls -d * | grep -P "${backupRegex}" | sort); do
                newCounter=$(($newCounter+1));
                rest=$((${countBackups}-${maxOldBackups}));
                if [ ${newCounter} -le ${rest} ]; then
                    rm -rf "${dir}" 2>> "${backupErrorLogFile}" &&
                    echo "Backup gelöscht: ${dir}" >> "${backupLogFile}";
                    oldDate=$(echo "${dir}" | cut  -d '-' -f 1,2,3);
                    oldBackupLogFile="${oldDate}-${backupName}.log";
                    rm "${oldBackupLogFile}" &&
                    echo "altes Logfile gelöscht: ${oldBackupLogFile}" >> "${backupLogFile}";
                    oldBackupLogFile="${oldDate}-${backupName}.err.log";
                    rm "${oldBackupLogFile}" &&
                    echo "altes Error-Logfile gelöscht: ${oldBackupLogFile}" >> "${backupLogFile}";
                fi
            done
        fi

        ### Finden des letzten Backups:

        lastBackup="$(ls -d * | grep -P "${backupRegex}" | sort | tail -n1)";
	if [ "${lastBackup}" = "${backupDateName}" ]; then
	    lastBackup="";
	fi

        ### Anlegen des neuen Backups:

        ## Stoppen der Dienste
        for service in ${servicesStopBevore[@]}; do
            service ${service} stop;
        done;

        if [ -z ${lastBackup} ]; then
            # erstes Backup:
            rsync -avu --exclude-from "${backupExludesFile}" --include-from "${backupIncludesFile}" "${sourceDir}" "${backupDir}/${backupDateName}" >> "${backupLogFile}" 2>> "${backupErrorLogFile}";
        else
            # wenn schon ein Backup existiert:
            rsync -avuH --link-dest="${backupDir}/${lastBackup}" --exclude-from "${backupExludesFile}" --include-from "${backupIncludesFile}" "${sourceDir}" "${backupDir}/${backupDateName}" >> "${backupLogFile}" 2>> "${backupErrorLogFile}";
        fi

        ## Starten der Dienste
        for service in ${servicesStartAfter[@]}; do
            service ${service} start;
        done;

        cd "${oldDir}";

    else
        logger -t "nightly-backup" "Fatal: Backup-Dir ${backupDir} kann nicht beschrieben werden.";
    fi
else
    logger -t "nightly-backup" "Fatal: Backup-Dir ${backupDir} nicht verfügbar!";
fi