#!/bin/bash #Enable pipefail to receive the error code of rsync and not only tee set -Eeuo pipefail trap 'on_error $LINENO' ERR on_error() { local line=$1 echo "ERROR: Script failed at line $line" >&2 if [ -f "$tmpLogFilePath" ]; then mailContent=$(cat "$tmpLogFilePath") else mailContent="Log file not available" fi { echo "To: $mailTo" echo "From: $mailFrom" echo "Subject: Backup FAILED (CRASH) on $(date +'%c')" echo "" echo "Script crashed at line $line" echo "" echo "$mailContent" } | sendmail -t exit 1 } #Check if path to the config file was provided if [ -z "$1" ] then echo "Please call this script with the path to the config file!" exit fi #Read the backup folders and configuration variables from the config script . $1 #Local variables globalErrors=0 logFilePath="${logPath}${logFileName}" #Rotate logs find $logPath -type f -mtime +$rotationDays -name '*.log' -execdir rm -- '{}' \; touch $tmpLogFilePath touch $logFilePath echo $logFilePath #Terminate if the last backup has not finished yet if pidof -o %PPID -x "$0" > /dev/null; then echo "Backup job already running. Exiting..." exit fi #Run the backup jobs as defined in the backup_folders array from the config echo "Starting backup job(s)" | tee $tmpLogFilePath for sourceFolder in "${!backup_folders[@]}" do #Exclude files IFS=';' read -ra split <<< "${backup_folders[$sourceFolder]}" #check if exclude file is not zero and file exists. Set to zero if not existing. excludeDIRs=${split[1]-} if [[ -n ${excludeDIRs} ]] && ! [ -f ${excludeDIRs} ]; then echo "Error: Could not find exclude file ${excludeDIRs}. Ignoring it." | tee -a $tmpLogFilePath excludeDIRs="" fi destinationFolder=${split[0]} mkdir -p ${destinationFolder} while [ "$retryAttempts" -ge "0" ] do echo "Starting Job" | tee -a $tmpLogFilePath echo "SRC: ${sourceFolder}" | tee -a $tmpLogFilePath echo "DEST: ${destinationFolder}" | tee -a $tmpLogFilePath echo "Exclude file: ${excludeDIRs}" | tee -a $tmpLogFilePath date | tee -a $tmpLogFilePath #SSH Host settings need to be set in the ssh client config! rsync --delete --out-format="%t %f %''b" -avz ${excludeDIRs:+"--exclude-from=$excludeDIRs"} ${sourceFolder} ${destinationFolder} 2>&1 | tee -a $tmpLogFilePath 2>&1 rsyncExitCode=$? echo "Ending backup job" | tee -a $tmpLogFilePath date | tee -a $tmpLogFilePath echo "" | tee -a $tmpLogFilePath if [ $rsyncExitCode -eq 0 ]; then break else echo "Error: rsync exited with code $rsyncExitCode. Retrying..." | tee -a $tmpLogFilePath retryAttempts=$((retryAttempts-1)) globalErrors=$((globalErrors+1)) fi done done #copy over cat $tmpLogFilePath > $logFilePath #Mail Notifications if [ $globalErrors -eq 0 ]; then #send mail for success echo -e "To:$mailTo\nFrom:$mailFrom\nSubject:Backup SUCCESSFUL on $(date +'%c')\n\n$(cat $tmpLogFilePath)" | sendmail $mailTo else #send mail for failure echo -e "To:$mailTo\nFrom:$mailFrom\nSubject:Backup FAILED on $(date +'%c')\n\n$(cat $tmpLogFilePath)" | sendmail $mailTo fi #delete tmp file rm $tmpLogFilePath