vm/not-supported/rsyncbackup.sh
szaimen ed0c57abdd
Some small enhancements to the backup scripts (#2043)
Signed-off-by: szaimen <szaimen@e.mail.de>
2021-07-10 09:31:32 +02:00

269 lines
9.3 KiB
Bash

#!/bin/bash
# T&M Hansson IT AB © - 2021, https://www.hanssonit.se/
# Copyright © 2021 Simon Lindner (https://github.com/szaimen)
true
SCRIPT_NAME="Rsync Backup"
SCRIPT_EXPLAINER="This script creates the off-shore backup of your server."
# shellcheck source=lib.sh
source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/nextcloud/vm/master/lib.sh)
# Check for errors + debug code and abort if something isn't right
# 1 = ON
# 0 = OFF
DEBUG=0
debug_mode
# Check if root
root_check
# Variables
LVM_MOUNT="/system"
START_TIME=$(date +%s)
CURRENT_DATE=$(date --date @"$START_TIME" +"%Y%m%d_%H%M%S")
CURRENT_DATE_READABLE=$(date --date @"$START_TIME" +"%d.%m.%Y - %H:%M:%S")
LOG_FILE="$VMLOGS/rsyncbackup-$CURRENT_DATE.log"
# This is needed for running via cron
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
# Functions
inform_user() {
echo -e "\n\n# $2"
print_text_in_color "$1" "$2"
}
paste_log_file() {
cat "$LOG_FILE" >> "$RSYNC_BACKUP_LOG"
echo -e "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" >> "$RSYNC_BACKUP_LOG"
}
remove_log_file() {
rm "$LOG_FILE"
}
show_drive_usage() {
inform_user "$ICyan" "Showing drive usage..."
lsblk -o FSUSE%,SIZE,MOUNTPOINT,NAME | grep -v "loop[0-9]" | grep "%" | sed 's|`-||;s/|-//;s/ | //'
echo ""
df -h | grep -v "loop[0-9]" | grep -v "tmpfs" | grep -v "^udev" | grep -v "^overlay"
}
send_error_mail() {
if [ -d "$BACKUP_TARGET_DIRECTORY" ]
then
inform_user "$ICyan" "Unmounting the off-shore backup drive..."
umount "$BACKUP_MOUNTPOINT"
fi
if [ -d "$BACKUP_SOURCE_DIRECTORY" ]
then
inform_user "$ICyan" "Unmounting the daily backup drive..."
umount "$BACKUP_SOURCE_MOUNTPOINT"
fi
get_expiration_time
inform_user "$IRed" "Off-shore backup sent error on $END_DATE_READABLE ($DURATION_READABLE)"
inform_user "$IRed" "Off-shore backup failed! $1"
if ! send_mail "Off-shore backup failed! $1" "$(cat "$LOG_FILE")"
then
notify_admin_gui \
"Off-shore backup failed! Though mail sending didn't work!" \
"Please look at the log file $LOG_FILE if you want to find out more."
paste_log_file
else
paste_log_file
remove_log_file
fi
exit 1
}
re_rename_snapshot() {
inform_user "$ICyan" "Re-renaming the snapshot..."
if ! lvrename /dev/ubuntu-vg/NcVM-snapshot-pending /dev/ubuntu-vg/NcVM-snapshot
then
return 1
else
return 0
fi
}
get_expiration_time() {
END_TIME=$(date +%s)
END_DATE_READABLE=$(date --date @"$END_TIME" +"%d.%m.%Y - %H:%M:%S")
DURATION=$((END_TIME-START_TIME))
DURATION_SEC=$((DURATION % 60))
DURATION_MIN=$(((DURATION / 60) % 60))
DURATION_HOUR=$((DURATION / 3600))
DURATION_READABLE=$(printf "%02d hours %02d minutes %02d seconds" $DURATION_HOUR $DURATION_MIN $DURATION_SEC)
}
# Write output to logfile.
exec > >(tee -i "$LOG_FILE")
exec 2>&1
# Start backup
inform_user "$IGreen" "Off-shore backup started! $CURRENT_DATE_READABLE"
# Check if the file exists
if ! [ -f "$SCRIPTS/off-shore-rsync-backup.sh" ]
then
send_error_mail "The off-shore-rsync-backup.sh doesn't exist."
fi
# Check if all needed variables are there (they get exported by the local off-shore-rsync-backup.sh)
if [ -z "$BACKUP_TARGET_DIRECTORY" ] || [ -z "$BACKUP_MOUNTPOINT" ] || [ -z "$RSYNC_BACKUP_LOG" ] \
|| [ -z "$BACKUP_SOURCE_MOUNTPOINT" ] || [ -z "$BACKUP_SOURCE_DIRECTORY" ]
then
send_error_mail "Didn't get all needed variables."
fi
# Check if pending snapshot is existing and cancel the backup in this case.
if does_snapshot_exist "NcVM-snapshot-pending"
then
msg_box "The snapshot pending does exist. Can currently not proceed.
Please try again later.\n
If you are sure that no update or backup is currently running, you can fix this by rebooting your server."
send_error_mail "NcVM-snapshot-pending exists. Please try again later!"
fi
# Check if snapshot can get created
if ! does_snapshot_exist "NcVM-snapshot"
then
send_error_mail "NcVM-snapshot doesn't exists."
fi
# Check if at least one daily backup drive has run
BORGBACKUP_LOG="$(grep "^export BORGBACKUP_LOG" "$SCRIPTS/daily-borg-backup.sh" \
| sed 's|.*BORGBACKUP_LOG="||' | sed 's|"$||')"
if [ -z "$BORGBACKUP_LOG" ] || ! [ -f "$BORGBACKUP_LOG" ] || ! grep -q "Backup finished on" "$BORGBACKUP_LOG"
then
send_error_mail "Not even one daily backup was successfully created. Please wait for that first."
fi
# Prepare backup repository
inform_user "$ICyan" "Mounting the daily backup drive..."
if ! [ -d "$BACKUP_SOURCE_DIRECTORY" ]
then
mount "$BACKUP_SOURCE_MOUNTPOINT" &>/dev/null
if ! [ -d "$BACKUP_SOURCE_DIRECTORY" ]
then
send_error_mail "Could not mount the daily backup drive. Is it connected?"
fi
fi
# Prepare backup repository
inform_user "$ICyan" "Mounting the off-shore backup drive..."
if ! [ -d "$BACKUP_TARGET_DIRECTORY" ]
then
mount "$BACKUP_MOUNTPOINT" &>/dev/null
if ! [ -d "$BACKUP_TARGET_DIRECTORY" ]
then
send_error_mail "Could not mount the off-shore backup drive. Please connect it!"
fi
fi
# Test if btrfs volume
if grep " $BACKUP_MOUNTPOINT " /etc/mtab | grep -q btrfs
then
IS_BTRFS_PART=1
mkdir -p "$BACKUP_MOUNTPOINT/.snapshots"
btrfs subvolume snapshot -r "$BACKUP_MOUNTPOINT" "$BACKUP_MOUNTPOINT/.snapshots/@$CURRENT_DATE"
while [ "$(find "$BACKUP_MOUNTPOINT/.snapshots/" -maxdepth 1 -mindepth 1 -type d -name '@*_*' | wc -l)" -gt 4 ]
do
DELETE_SNAP="$(find "$BACKUP_MOUNTPOINT/.snapshots/" -maxdepth 1 -mindepth 1 -type d -name '@*_*' | sort | head -1)"
btrfs subvolume delete "$DELETE_SNAP"
done
fi
# Send mail that backup was started
if ! send_mail "Off-shore backup started!" "You will be notified again when the backup is finished!
Please don't restart or shutdown your server until then!"
then
notify_admin_gui "Off-shore backup started!" "You will be notified again when the backup is finished!
Please don't restart or shutdown your server until then!"
fi
# Check if pending snapshot is existing and cancel the backup in this case.
if does_snapshot_exist "NcVM-snapshot-pending"
then
msg_box "The snapshot pending does exist. Can currently not proceed.
Please try again later.\n
If you are sure that no update or backup is currently running, you can fix this by rebooting your server."
send_error_mail "NcVM-snapshot-pending exists. Please try again later!"
fi
# Rename the snapshot to represent that the backup is pending
inform_user "$ICyan" "Renaming the snapshot..."
if ! lvrename /dev/ubuntu-vg/NcVM-snapshot /dev/ubuntu-vg/NcVM-snapshot-pending
then
send_error_mail "Could not rename the snapshot to snapshot-pending."
fi
# Create the backup
inform_user "$ICyan" "Creating the off-shore backup..."
if ! rsync --archive --human-readable --delete --stats "$BACKUP_SOURCE_DIRECTORY/" "$BACKUP_TARGET_DIRECTORY"
then
show_drive_usage
re_rename_snapshot
send_error_mail "Something failed during the rsync job."
fi
# Adjust permissions and scrub volume
if [ -n "$IS_BTRFS_PART" ]
then
inform_user "$ICyan" "Adjusting permissions..."
find "$BACKUP_MOUNTPOINT/" -not -path "$BACKUP_MOUNTPOINT/.snapshots/*" \
\( ! -perm 600 -o ! -group root -o ! -user root \) -exec chmod 600 {} \; -exec chown root:root {} \;
inform_user "$ICyan" "Making sure that all data is written out correctly by waiting 10 min..."
# This fixes an issue where checksums are not yet created before the scrub command runs which then reports checksum errors
if ! sleep 10m
then
re_rename_snapshot
send_error_mail "Some errors were reported while waiting for the data to get written out."
fi
inform_user "$ICyan" "Scrubbing BTRFS partition..."
if ! btrfs scrub start -B "$BACKUP_MOUNTPOINT"
then
re_rename_snapshot
send_error_mail "Some errors were reported while scrubbing the BTRFS partition."
fi
fi
# Rename the snapshot back to normal
if ! re_rename_snapshot
then
send_error_mail "Could not rename the snapshot-pending to snapshot."
fi
# Print usage of drives into log
show_drive_usage
# Unmount the backup drive
inform_user "$ICyan" "Unmounting the off-shore backup drive..."
if mountpoint -q "$BACKUP_MOUNTPOINT" && ! umount "$BACKUP_MOUNTPOINT"
then
send_error_mail "Could not unmount the off-shore backup drive!"
fi
# Unmount the backup drive
inform_user "$ICyan" "Unmounting the daily backup drive..."
if mountpoint -q "$BACKUP_SOURCE_MOUNTPOINT" && ! umount "$BACKUP_SOURCE_MOUNTPOINT"
then
send_error_mail "Could not unmount the daily backup drive!"
fi
# Resetting the timer for off-shore backups
inform_user "$ICyan" "Resetting the timer for off-shore backups..."
sed -i 's|^DAYS_SINCE_LAST_BACKUP.*|DAYS_SINCE_LAST_BACKUP=0|' "$SCRIPTS/off-shore-rsync-backup.sh"
# Show expiration time
get_expiration_time
inform_user "$IGreen" "Off-shore backup finished on $END_DATE_READABLE ($DURATION_READABLE)"
# Send mail about successful backup
if ! send_mail "Off-shore backup successful! You can now disconnect the off-shore backup drive!" "$(cat "$LOG_FILE")"
then
notify_admin_gui \
"Off-shore backup successful! Though mail sending didn't work!" \
"You can now disconnect the off-shore backup drive! \
Please look at the log file $LOG_FILE if you want to find out more."
paste_log_file
else
paste_log_file
remove_log_file
fi
exit