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.
This commit is contained in:
ducoterra
2022-02-01 10:47:08 -05:00
parent 9a3ee4fa9b
commit c8396037db

View File

@@ -1,6 +1,6 @@
#!/bin/bash
export SOURCE_DIR=${SOURCE_DIR:=root}
export SOURCE_DIR=${SOURCE_DIR:=/}
# Fix basename / showing up as "/" -> change to "root"
if [ $(basename $SOURCE_DIR) = / ]; then
export SNAPSHOT_PREFIX=${SNAPSHOT_PREFIX:=root}
@@ -25,27 +25,58 @@ 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
# Check if backup disk is mounted
# Attempt to mount backup disk
mount $BACKUP_DRIVE_MNT
mountpoint $BACKUP_DRIVE_MNT
if [ $? = 0 ]; then
if [ -d $BACKUP_DIR/$LATEST ]; then
# 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 snapshot dir
rm -f $SNAPSHOT_DIR/$LATEST
ln -s $SNAPSHOT_DIR/$SNAPSHOT_NAME $SNAPSHOT_DIR/$LATEST
# 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