aboutsummaryrefslogtreecommitdiff
path: root/rsync-backup.sh
diff options
context:
space:
mode:
Diffstat (limited to 'rsync-backup.sh')
-rwxr-xr-xrsync-backup.sh299
1 files changed, 0 insertions, 299 deletions
diff --git a/rsync-backup.sh b/rsync-backup.sh
deleted file mode 100755
index 0c48018..0000000
--- a/rsync-backup.sh
+++ /dev/null
@@ -1,299 +0,0 @@
-#!/bin/bash
-#
-# rsync-backup.sh - a backup script using rsync.
-#
-# Copyright 2015 - 2018 Einhard Leichtfuß
-#
-# This file is part of rsync-backup.
-#
-# rsync-backup is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# rsync-backup is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with rsync-backup. If not, see <https://www.gnu.org/licenses/>.
-#
-
-RSYNC=rsync
-
-typeset -a rsync_args
-typeset -a rsync_inc_args
-typeset -A bakpath
-typeset filter_file_all # Applied after specific filter.
-typeset -A filter_file
-
-# Default arguments for rsync (-rptogAXlHS, --timeout, --info).
-rsync_args=(
- --recursive
- --perms --times --owner --group
- --acls --xattrs
- --links
- --hard-links
- --sparse
- --timeout=60
- #-vv
- --info=progress2
- )
-
-# Supplemental arguments for rsync; only used when an actual incremental
-# update is performed, i.e. when --link-dest is used.
-rsync_inc_args=(
- --fuzzy --fuzzy
- )
-
-filter_file_all=/etc/rsync-backup/filter
-
-config=/etc/rsync-backup/backup.conf
-source "$config"
-
-src=/home/respiranto/txt/bash/rsync-backup/src
-dest=/home/respiranto/txt/bash/rsync-backup/dest
-
-typeset -l reply
-typeset -i i n
-
-# RSYNC args.
-# basic args: --recursive --perms --times --owner --group --links
-# extra args: --sparse --acls --xattrs --hard-links --timeout=60
-# --fuzzy --fuzzy
-# --filter="merge <file>"
-# likely: --compress
-# --partial{,dir=DIR}
-# --progress
-# possibly: --devices --specials
-# --max-size=SIZE-OF-FILE
-# --one-file-system
-# --log-file=FILE --log-file-format=FORMAT
-# --human-readable
-# unlikely: --omit-{dir,link}-times --update (!--inplace) --delete
-# --exclude
-# great: --link-dest=DIR (timestamps?)
-# testing: --verbose --dry-run (-vn)
-# interesting: --sockopts --itemize-changes --out-format=FORMAT
-# --stats
-
-function main
-{
- # In case of a non-matching wildcard, return nothing.
- shopt -s nullglob
- # Include dotfiles (except . and ..) in regex matching.
- shopt -s dotglob
-
- get_args "$@" || return $?
-
- check_paths || return $?
-
- # Change the separation char to $'\n' to avoid confusion with filenames
- # containing spaces (default is $' \t\n').
- IFS=$'\n'
-
- find_existing_backup_dirs || return $?
-
- perform_backup || return $?
-
- refresh_symlinks || return $?
-}
-
-
-function get_args
-{
- if [ $# -eq 0 ]
- then
- echo "Usage: $0 <src> [<dest>]"
- return 1
- fi
-
- dirpath="$(realpath "$1")"
-
- if [ $# -gt 1 ]
- then
- bakpath="$(realpath $2)"
- elif test -v bakpath[$dirpath]
- then
- bakpath="${bakpath[$dirpath]}"
- else
- echo "Error: Backup path for $dirpath not configured."
- return 1
- fi
-
- filter_args=()
- if test -v filter_file[$dirpath] && test -f "${filter_file[$dirpath]}"
- then
- filter_args+=("--filter=merge ${filter_file[$dirpath]}")
- fi
- if test -v filter_file_all -a -f "$filter_file_all"
- then
- filter_args+=("--filter=merge ${filter_file_all}")
- fi
-}
-
-
-function check_paths
-{
- # Test whether the dirs exist already.
- if ! test -d "$dirpath"
- then
- echo "Source (\"$dirpath\") does not exist."
- return 1
- fi
-
- if ! test -d "$bakpath"
- then
- echo "Target (\"$bakpath\") does not exist."
- echo -n "Do you want do create it [y/N]? "
- read reply
- if [[ "$reply" != "y" && "$reply" != "yes" ]]
- then
- return 1
- fi
-
- if ! mkdir -p "$bakpath"
- then
- echo "Backup creation has failed."
- echo "\"$bakpath\" could not be created."
- return 1
- fi
- fi
-}
-
-
-function find_existing_backup_dirs
-{
- n=0
- for file in `ls "$bakpath"`; do
- if test -d $bakpath/$file \
- && [[ "$file" =~ ^[0-9]{4}-[0-1][0-9]-[0-3][0-9]_[0-2][0-9]([0-5][0-9]){2}.backup$ ]]
- then
- dirs[n]="$file"
- n+=1
- fi
- done
-}
-
-
-# $1 path
-# $2 error message: string
-function clear_file
-{
- if test -e "$1" -o -L "$1"; then
- echo "It seems like the last backup process failed or you have created" \
- "the file \"$1\" manually."
- echo -n "Do you want to delete it [y/N]? "
- read reply
- if [[ "$reply" == "y" || "$reply" == "yes" ]]
- then
- printf "Deleting"
- if rm -rf "$1"; then
- printf " - done\n"
- return 0
- else
- printf '\n%s\n' "$2"
- printf 'The file \"%s\" could not be deleted.\n' "$1"
- return 1
- fi
- else
- printf '%s\n' "$2"
- printf '%s %s\n' "Please remove the above mentioned file manually" \
- "or run this script once more."
- return 1
- fi
- fi
- return 0
-}
-
-
-function perform_backup
-{
- bakdate=`date +%Y-%m-%d_%H%M%S.backup`
- finaldir="$bakpath/$bakdate"
- tempdir="$bakpath/new.backup"
- clear_file "$tempdir" "Backup creation has failed." || return 1
- clear_file "$finaldir" "Backup creation has failed." || return 1
-
- # note: $n == ${#dirs[@]}
- printf 'Starting backup nr. %u.\n' "$n"
- if [ $n -eq 0 ]
- then
- # Perform first backup, not incremental.
- $RSYNC "${rsync_args[@]}" \
- "${filter_args[@]}" \
- "$dirpath"/ "$tempdir" \
- || return 1
- else
- # Perform incremental backup on the basis of the last.
- $RSYNC "${rsync_args[@]}" \
- "${rsync_inc_args[@]}" --link-dest="${bakpath}/${dirs[n-1]}" \
- "${filter_args[@]}" \
- "$dirpath"/ "$tempdir" \
- || return 1
- fi
-
- mv "$tempdir" "$finaldir" || return 1
- printf '\nCreating of backup nr. %u succesfully executed.\n' "$n"
-}
-
-
-function refresh_symlinks
-{
- linkdir="$bakpath/latest"
- if test -L "$linkdir"
- then
- rm "$linkdir"
- ln -s "$bakdate" "$linkdir"
- elif clear_file "$linkdir" "Creation of softlink \"$linkdir\" failed."
- then
- ln -s "$bakdate" "$linkdir"
- fi
-
- # by_number
- numdir="$bakpath/by_number"
- if ! test -d "$numdir"
- then
- if clear_file "$numdir" "Creating directory $numdir failed."
- then
- mkdir "$numdir"
- else
- return 1
- fi
- fi
-
- for file in "$numdir"/*
- do
- if test -L "$file"
- then
- rm "$file"
- else
- if ! clear_file "$file" "Setting up numbered softlinks failed."
- then
- return 1
- fi
- fi
- done
-
- dirs[$n]="$bakdate" # Set last dir on current.
-
- max_digits=${#n}
- zeros[max_digits]=''
- i=$max_digits-1
- while [ $i -ge 1 ]
- do
- zeros[i]=${zeros[i+1]}0
- i+=-1
- done
-
- i=0
- while [ $i -le $n ]
- do
- ln -s "../${dirs[i]}" "$numdir/${zeros[${#i}]}$i"
- i+=1
- done
-}
-
-
-main "$@"