Files
Workstation/ansible/arch_backup/files/scripts/btrfs_backup.sh
ducoterra c8396037db Fix backup snapshot drift
Occasionally, the latest snapshot in the snapshots dir would get out of
sync with the backup drive. Change the script to detect drift and fix it
before performing a backup.
2022-02-01 10:47:08 -05:00

83 lines
3.0 KiB
Bash
Executable File

#!/bin/bash
export SOURCE_DIR=${SOURCE_DIR:=/}
# Fix basename / showing up as "/" -> change to "root"
if [ $(basename $SOURCE_DIR) = / ]; then
export SNAPSHOT_PREFIX=${SNAPSHOT_PREFIX:=root}
else
export SNAPSHOT_PREFIX=${SNAPSHOT_PREFIX:=$(basename $SOURCE_DIR)}
fi
# Set snapshot prefix based on basename
export SNAPSHOT_TIME=$(date +"%y_%m_%d-%H.%M")
export SNAPSHOT_NAME=$SNAPSHOT_PREFIX-$SNAPSHOT_TIME
export SNAPSHOT_DIR=${SNAPSHOT_DIR:=/.snapshots}
export LATEST=$SNAPSHOT_PREFIX-latest
export BACKUP_DRIVE_MNT=${BACKUP_DRIVE_MNT:=/mnt/backup0}
export BACKUP_DIR=${BACKUP_DIR:=/mnt/backup0/DucoBacktop}
# Show snapshot settings
echo "SOURCE_DIR: $SOURCE_DIR"
echo "SNAPSHOT_PREFIX: $SNAPSHOT_PREFIX"
echo "SNAPSHOT_TIME: $SNAPSHOT_TIME"
echo "SNAPSHOT_NAME: $SNAPSHOT_NAME"
echo "SNAPSHOT_DIR: $SNAPSHOT_DIR"
echo "LATEST: $LATEST"
echo "BACKUP_DRIVE_MNT: $BACKUP_DRIVE_MNT"
echo "BACKUP_DIR: $BACKUP_DIR"
# Sync latest backups
# The "latest" symlinks can get out of sync for a variety of reasons,
# including backups run while the disk is unplugged.
# They must be kept in sync so that snapshots are sent with a parent
# that actually exists on the backup drive
#
# In order to keep them in sync we'll do the following:
# 1. Check the <backup>-latest on the backup drive matches
# <backup>-latest in the snapshot directory
# 2. If they don't match, assume the backup drive has the correct
# snapshot. Replace the <backup>-latest symlink in the snapshots
# directory with the one from the backup drive
#
# First check if the symlinks exist
if [ -L $SNAPSHOT_DIR/$LATEST ] && [ -L $BACKUP_DIR/$LATEST ]
then
# Get the actual name of the latest backup
LATEST_SNAPSHOT=$(basename $(readlink $SNAPSHOT_DIR/$LATEST))
LATEST_BACKUP=$(basename $(readlink $BACKUP_DIR/$LATEST))
# If the latest backups don't match
if [ $LATEST_SNAPSHOT != $LATEST_BACKUP ]
then
echo "Detected drift. Synchronizing latest snapshot with backup. Set to $LATEST_BACKUP."
# Remove and replace the snapshot directory's latest
rm $SNAPSHOT_DIR/$LATEST
ln -s $SNAPSHOT_DIR/$LATEST_BACKUP $SNAPSHOT_DIR/$LATEST
fi
fi
# Create readonly snapshot
btrfs subvolume snapshot -r $SOURCE_DIR $SNAPSHOT_DIR/$SNAPSHOT_NAME
# Attempt to mount backup disk
mount $BACKUP_DRIVE_MNT
# Check if backup disk is mounted
mountpoint $BACKUP_DRIVE_MNT
if [ $? = 0 ]; then # backup drive mounted
# If we have a latest, use it as the parent
if [ -L $BACKUP_DIR/$LATEST ]; then
btrfs send -p $SNAPSHOT_DIR/$LATEST $SNAPSHOT_DIR/$SNAPSHOT_NAME | btrfs receive $BACKUP_DIR
else
btrfs send $SNAPSHOT_DIR/$SNAPSHOT_NAME | btrfs receive $BACKUP_DIR
fi
# Update latest in backup dir
rm -f $BACKUP_DIR/$LATEST
ln -s $BACKUP_DIR/$SNAPSHOT_NAME $BACKUP_DIR/$LATEST
else
echo "Backup location $BACKUP_DRIVE_MNT not mounted. Snapshot $SNAPSHOT_NAME not synced"
fi
# Update latest in snapshot dir
rm -f $SNAPSHOT_DIR/$LATEST
ln -s $SNAPSHOT_DIR/$SNAPSHOT_NAME $SNAPSHOT_DIR/$LATEST