hennymugge

Members
  • Posts

    2
  • Joined

  • Last visited

hennymugge's Achievements

Noob

Noob (1/14)

0

Reputation

  1. Hi Mgutt, Really loving your script and think it might become really useful for my usecase, being: backing up via rsync through ssh on port 8888 to an external server. I'm getting close but I do have some issues. The first being that the log file isn't uploaded to the server, but placed in the folder of the backup-file (in my case /var/backups/backup_script.sh) Using this script, rsync is starting as supposed but hasn't been able to finish yet due to a random broken pipe error... Any help would be greatly appreciated! #!/bin/bash # ##################################### # Script: rsync Incremental Backup v0.3 # Description: Creates incremental backups and deletes outdated versions # Author: Marc Gutt # # Changelog: # 0.3 # - rsync returns summary # - typo in notification corrected # - skip some rsync errors (defaults are "0" = skip on success and "24" = skip if some files vanish from the source while transfer) # - add timeout for backup renaming https://forums.unraid.net/topic/97958-rsync-incremental-backup/?tab=comments#comment-910188 # 0.2 # - use full path for source and destination # - backup multiple paths # - unraid notification on success is now optional # 0.1 # - initial release # # ######### Settings ################## source_paths=( "/media/data" ) backup_path="username@hostname:~/backup" days=14 # preserve backups of the last X days months=12 # preserve backups of the first day of the last X month years=3 # preserve backups of the first january of the last X years fails=3 # preserve the recent X failed backups notification=0 skip_errors=(0 24) # https://linux.die.net/man/1/rsync#:~:text=Exit%20Values rename_timeout=100 # ##################################### # # ######### Script #################### # make script race condition safe if [[ -d "/tmp/${0///}" ]] || ! mkdir "/tmp/${0///}"; then exit 1; fi; trap 'rmdir "/tmp/${0///}"' EXIT; # check user settings backup_root_path=$([[ "${backup_path: -1}" == "/" ]] && echo "${backup_path%?}" || echo "$backup_path") # loop through all source paths for source_path in "${source_paths[@]}"; do echo "Create backup of $source_path" backup_path="$backup_root_path" # check user settings source_path=$([[ "${source_path: -1}" == "/" ]] && echo "${source_path%?}" || echo "$source_path") # shorten the backup path if [[ $source_path == "/mnt/user"* ]]; then backup_path+="/Shares${source_path#'/mnt/user'}" echo "Backup path has been set to $backup_path" elif [[ $source_path == "/mnt"* ]]; then backup_path+="${source_path#'/mnt'}" echo "Backup path has been set to $backup_path" fi # new backup timestamp new_backup="$(date +%Y%m%d_%H%M%S)" # create directory tree as rsync is not able to do that (https://askubuntu.com/a/561239/227119) mkdir -p "${backup_path}/.${new_backup}" # create log file exec &> >(tee "${backup_path}/.${new_backup}/backup.log") # obtain most recent backup last_backup=$(ls -t "${backup_path}" | head -n1) # create incremental backup if [[ -n "${last_backup}" ]]; then echo "Create incremental backup ${new_backup} by using last backup ${last_backup}" rsync -av --stats --delete -e "ssh -p 8888 -i /home/username/.ssh/id_rsa" --link-dest="${backup_path}/${last_backup}" "${source_path}" "${backup_path}/.${new_backup}" else echo "Create full backup ${new_backup}" # create very first backup rsync -av --stats -e "ssh -p 8888 -i /home/username/.ssh/id_rsa" "${source_path}" "${backup_path}/.${new_backup}" fi rsync_status=$? job_name="$(dirname "$0")" job_name="$(basename "$job_name")" if [[ "${skip_errors[@]}" =~ "${rsync_status}" ]]; then if [ "$notification" = "1" ]; then /usr/local/emhttp/webGui/scripts/notify -i normal -s "Backup done." -d "Job $job_name:${backup_path}/${new_backup} successfully finished." fi # make backup visible rename_try=1 while true; do sleep 1 echo "Try #${rename_try} to make backup visible" mv "${backup_path}/.${new_backup}" "${backup_path}/${new_backup}" mv_status=$? if [[ $mv_status -eq 0 ]]; then break fi rename_try=$(($rename_try+1)) if [[ $rename_try -ge rename_timeout ]]; then /usr/local/emhttp/webGui/scripts/notify -i alert -s "Backup failed!" -d "Job $job_name:${backup_path}/${new_backup} failed because rename timeout has been reached!" break; fi done else /usr/local/emhttp/webGui/scripts/notify -i alert -s "Backup failed!" -d "Job $job_name:${backup_path}/${new_backup} failed (error ${rsync_status})!" fi # clean up ls -tA "${backup_path}/" | while read backup; do if [ "${backup:0:1}" = "." ]; then if [ "$fails" -gt "0" ]; then echo "Preserve failed backup: $backup" fails=$(($fails-1)) continue fi echo "Delete failed backup: $backup" rm -r "${backup_path}/${backup}" continue fi last_year=$year last_month=$month last_day=$day year=${backup:0:4} month=${backup:4:2} day=${backup:6:2} if [ "$last_day" = "$day" ] && [ "$last_month" = "$month" ] && [ "$last_year" = "$year" ]; then echo "Keep multiple backups per day: $backup" continue fi # preserve yearly backups if [ "$month" = "01" ] && [ "$day" = "01" ] && [ "$years" -gt "0" ]; then echo "Preserve yearly backup: $backup" years=$(($years-1)) continue fi # preserve monthly backups if [ "$day" = "01" ] && [ "$months" -gt "0" ]; then echo "Preserve monthly backup: $backup" months=$(($months-1)) continue fi # preserve daily backups if [ "$days" -gt "0" ]; then echo "Preserve daily backup: $backup" days=$(($days-1)) continue fi echo "Delete $backup" rm -r "${backup_path}/${backup}" done done