random-scripts/do-backup

150 lines
5.1 KiB
Bash
Executable file

#!/bin/bash
# Version: 0.1.1
# Copyright (c) 2023:
# Darren 'Tadgy' Austin <darren (at) afterdark.org.uk>
# Licensed under the terms of the GNU General Public License version 3.
#
# Perform backup tasks in a generic way.
# Base configuration.
RSYNC_OPTIONS=( '-a' '-H' '-A' '--timeout=300' '--partial' '--partial-dir=.rsync-tmp' '--delete-delay' '--delay-updates' )
RSYNC_OPTIONS_VERBOSE=( '--verbose' '--stats' '--human-readable' )
RSYNC_LOG="/tmp/${0##*/}-$$.log"
# Sanity checks.
(( $# != 1 )) || [[ -z "$1" ]] || [[ "$1" =~ ^(-h|-help|--help)$ ]] && {
printf "%s: %s <%s>\\n" "Usage" "$0" "backup definition" >&2
exit 1
}
# Get backup definition specific configuration.
case "$1" in
'gv0')
BACKUP_MOUNTPOINT="/localdata"
BACKUP_DESTDIR="$BACKUP_MOUNTPOINT/backups/gv0"
RSYNC_SOURCE="/storage/gv0/" # The / on the end is required.
RSYNC_FILTER=()
;;
'mirrors')
BACKUP_MOUNTPOINT="/localdata"
BACKUP_DESTDIR="$BACKUP_MOUNTPOINT/backups/mirrors"
RSYNC_SOURCE="slackware.uk::mirrors/" # The / on the end is required.
RSYNC_FILTER=( \
'--include=/absolute/***' \
'--include=/csb/***' \
'--include=/cumulative/***' \
'--include=/freeslack/***' \
'--include=/gfs/***' \
'--include=/microlinux/***' \
'--include=/msb/***' \
'--include=/sarpi/***' \
'--include=/slackonly/***' \
'--include=/slackvirt/***' \
'--include=/slackware/' \
'--include=/slackware/slackware-pre-1.0-beta/***' \
'--include=/slackware/slackware-1.01/***' \
'--include=/slackwarearm/***' \
'--include=/slacky/***' \
'--include=/slaxbmc/***' \
'--include=/slint/***' \
'--include=/sls/***' \
'--include=/studioware/***' \
'--exclude=*' )
RSYNC_OPTIONS+=( '--contimeout=30' )
;;
'userdir')
BACKUP_MOUNTPOINT="/data/home"
BACKUP_DESTDIR="$BACKUP_MOUNTPOINT/tadgy/UserDirs/${HOSTNAME%%.*}-$USER"
RSYNC_SOURCE="/home/$USER/" # The / on the end is required.
RSYNC_FILTER=( \
'--exclude=/.cache/mozilla/firefox/*/cache2/***' \
'--exclude=/.gnupg/private-keys-v1.d/*.key' \
'--exclude=/.gnupg/openpgp-revocs.d/*.rev' \
'--exclude=/.irssi/config' \
'--exclude=/.ssh/id_ed25519' \
'--exclude=/.ssh/id_rsa' )
ERRORS_SOURCE="userdir: ${HOSTNAME%%.*}-$USER"
;;
*)
printf "%s: %s: %s\\n" "${0##*/}" "$1" "unknown backup definition" >&2
exit 1
;;
esac
# Only allow one copy of the script to run at any time.
# shellcheck disable=SC2154
if [[ "$FLOCK" != "$0" ]]; then
# shellcheck disable=SC2093
exec env FLOCK="$0" flock -E 10 -e -n "$0" "$0" "$@"
ERR="$?"
if (( ERR == 10 )); then
# File is locked, exit now.
exit 0
elif (( ERR > 0 )); then
printf "%s: %s\\n" "${0##*/}" "flock execution error" >&2
exit 1
fi
fi
# Source the mail configuration.
source /etc/mail.conf "backups" 2>/dev/null || {
printf "%s: %s\\n" "${0##*/}" "Failed to source /etc/mail.conf" >&2
exit 1
}
# Make sure BACKUP_MOUNTPOINT is a mountpoint.
mountpoint "$BACKUP_MOUNTPOINT" >/dev/null 2>&1 || {
[[ -x /opt/bin/pushover-client ]] && /opt/bin/pushover-client "backups" -p -1 -m "Backup failure: ${ERRORS_SOURCE:-$RSYNC_SOURCE}"
if [[ -n "${EMAIL_TO[*]}" ]]; then
mailx "${MAILX_ARGS[@]}" -S "from=$EMAIL_FROM" -s "Backup failure: ${ERRORS_SOURCE:-$RSYNC_SOURCE}" "${EMAIL_TO[@]}" <<-EOF 2>/dev/null || \
printf "%s: %s\\n" "${0##*/}" "mailx command failed" >&2
'$BACKUP_MOUNTPOINT' is not a mountpoint.
EOF
exit 1
else
printf "%s: %s\\n" "${0##*/}" "no recipient configured for mail delivery" >&2
exit 1
fi
}
# Create the BACKUP_DESTDIR if required.
[[ ! -e "$BACKUP_DESTDIR" ]] && {
mkdir -p "$BACKUP_DESTDIR" || {
[[ -x /opt/bin/pushover-client ]] && /opt/bin/pushover-client "backups" -p -1 -m "Backup failure: ${ERRORS_SOURCE:-$RSYNC_SOURCE}"
if [[ -n "${EMAIL_TO[*]}" ]]; then
mailx "${MAILX_ARGS[@]}" -S "from=$EMAIL_FROM" -s "Backup failure: ${ERRORS_SOURCE:-$RSYNC_SOURCE}" "${EMAIL_TO[@]}" <<-EOF 2>/dev/null || \
printf "%s: %s\\n" "${0##*/}" "mailx command failed" >&2
Failed to mkdir '$BACKUP_DESTDIR'.
EOF
exit 1
else
printf "%s: %s\\n" "${0##*/}" "no recipient configured for mail delivery" >&2
exit 1
fi
}
}
# Do the backup.
rsync "${RSYNC_OPTIONS[@]}" "${RSYNC_OPTIONS_VERBOSE[@]}" "${RSYNC_FILTER[@]}" "$RSYNC_SOURCE" "$BACKUP_DESTDIR" >"$RSYNC_LOG" 2>&1
ERR="$?"
# Send a notification and mail a log if there were errors.
(( ERR != 0 )) && (( ERR != 10 )) && (( ERR != 24 )) && {
[[ -x /opt/bin/pushover-client ]] && /opt/bin/pushover-client "backups" -p -1 -m "Backup failure: ${ERRORS_SOURCE:-$RSYNC_SOURCE}"
if [[ -n "${EMAIL_TO[*]}" ]]; then
mailx "${MAILX_ARGS[@]}" -S "from=$EMAIL_FROM" -s "Backup failure: ${ERRORS_SOURCE:-$RSYNC_SOURCE}" "${EMAIL_TO[@]}" <<-EOF 2>/dev/null || \
printf "%s: %s\\n" "${0##*/}" "mailx command failed" >&2
Exit code: $ERR
Output:
$(< "$RSYNC_LOG")
EOF
RET=1
else
printf "%s: %s\\n" "${0##*/}" "no recipient configured for mail delivery" >&2
RET=1
fi
}
rm -f "$RSYNC_LOG"
exit "${RET:-0}"