From 39b0c5726686431a9c233454d34bbacdd0ee4314 Mon Sep 17 00:00:00 2001 From: albert Date: Wed, 18 Dec 2024 14:19:13 -0600 Subject: [PATCH] Update backup script --- .../software/cli/scripts/btrfs-backup.sh | 81 ++++++++++++------- wallpapers | 2 +- 2 files changed, 52 insertions(+), 31 deletions(-) diff --git a/nixos/common/software/cli/scripts/btrfs-backup.sh b/nixos/common/software/cli/scripts/btrfs-backup.sh index 60622087..4362ef53 100755 --- a/nixos/common/software/cli/scripts/btrfs-backup.sh +++ b/nixos/common/software/cli/scripts/btrfs-backup.sh @@ -1,5 +1,4 @@ #!/usr/bin/env bash -#!/bin/bash # Check for required argument if [ $# -ne 1 ]; then @@ -10,6 +9,7 @@ fi # Configuration SNAPPER_CONFIG="$1" +BACKUP_DESCRIPTION="btrfs-backup" # Get the actual snapshot location from snapper config SOURCE_PATH=$(sudo snapper -c "$SNAPPER_CONFIG" get-config | grep '^SUBVOLUME' | cut -d'=' -f2 | tr -d '"'| awk {'print $3'}) @@ -26,17 +26,22 @@ if [ ! -d "$SNAPSHOT_PATH" ]; then exit 1 fi +# Create new snapshot with backup description +NEW_SNAPSHOT=$(sudo snapper -c "$SNAPPER_CONFIG" create --description "$BACKUP_DESCRIPTION" --print-number) +if [ -z "$NEW_SNAPSHOT" ]; then + echo "ERROR: Failed to create new snapshot" + exit 1 +fi -# Get latest snapshot number from snapper -LATEST_SNAPSHOT=$(sudo snapper -c "$SNAPPER_CONFIG" list | tail -n 1 | awk '{print $1}') HOSTNME=$(hostname) REMOTE_HOST="root@synology" BASE_DEST_PATH="/volume1/BTRFS_Receives/`hostname`/${SNAPPER_CONFIG}" -DEST_PATH="/volume1/BTRFS_Receives/`hostname`/${SNAPPER_CONFIG}/${LATEST_SNAPSHOT}" +DEST_PATH="/volume1/BTRFS_Receives/`hostname`/${SNAPPER_CONFIG}/${NEW_SNAPSHOT}" STATE_FILE="/var/lib/snapper-backup-${SNAPPER_CONFIG}.state" LOG_FILE="/var/log/snapper-backup-${SNAPPER_CONFIG}.log" KEEP_SNAPSHOTS=5 -# Get latest successful transfer number + +# Get latest successful transfer number from snapshots with backup description LAST_TRANSFERRED=$(cat "$STATE_FILE" 2>/dev/null || echo "") # Ensure we exit on any error @@ -73,24 +78,40 @@ verify_remote() { # Function to get remote snapshots get_remote_snapshots() { - ssh "$REMOTE_HOST" "find '$BASE_DEST_PATH' -maxdepth 2 -type d -name 'snapshot*' | sort -n" - # ssh "$REMOTE_HOST" "btrfs subvolume list /volume1/ -t | grep $HOSTNAME | grep $SNAPPER_CONFIG" + ssh "$REMOTE_HOST" "find '$BASE_DEST_PATH' -maxdepth 1 -type d -name '[0-9]*' | sort -n" } -# Function to cleanup old remote snapshots -cleanup_remote_snapshots() { - local snapshots=($(get_remote_snapshots)) - local count=${#snapshots[@]} +# Function to get local backup snapshots +get_local_snapshots() { + sudo snapper -c "$SNAPPER_CONFIG" list | grep "$BACKUP_DESCRIPTION" | awk '{print $1}' | sort -n +} + +# Function to cleanup old snapshots both locally and remotely +cleanup_snapshots() { + local local_snapshots=($(get_local_snapshots)) + local remote_snapshots=($(get_remote_snapshots)) + local count=${#local_snapshots[@]} if [ $count -gt $KEEP_SNAPSHOTS ]; then local to_delete=$((count - KEEP_SNAPSHOTS)) - log "Cleaning up $to_delete old snapshots on remote system" + log "Cleaning up $to_delete old snapshots both locally and remotely" for ((i=0; i<$to_delete; i++)); do - local snapshot="${snapshots[$i]}" - log "Deleting remote snapshot: $snapshot" - ssh "$REMOTE_HOST" "btrfs subvolume delete '$snapshot'" || \ - log "WARNING: Failed to delete snapshot $snapshot" + local snapshot="${local_snapshots[$i]}" + + # Delete remote snapshot first + if ssh "$REMOTE_HOST" "[ -d '$BASE_DEST_PATH/$snapshot' ]"; then + log "Deleting remote snapshot: $snapshot" + ssh "$REMOTE_HOST" "btrfs subvolume delete '$BASE_DEST_PATH/$snapshot/snapshot'" || \ + log "WARNING: Failed to delete remote snapshot $snapshot" + ssh "$REMOTE_HOST" "rm -rf '$BASE_DEST_PATH/$snapshot'" || \ + log "WARNING: Failed to cleanup remote snapshot directory $snapshot" + fi + + # Then delete local snapshot + log "Deleting local snapshot: $snapshot" + sudo snapper -c "$SNAPPER_CONFIG" delete "$snapshot" || \ + log "WARNING: Failed to delete local snapshot $snapshot" done fi } @@ -98,60 +119,60 @@ cleanup_remote_snapshots() { # Start backup process log "Starting backup for snapper config: $SNAPPER_CONFIG" log "Using snapshot path: $SNAPSHOT_PATH" +log "Created new snapshot: $NEW_SNAPSHOT" # Verify remote connectivity first verify_remote # Verify snapshots exist -verify_snapshot "$LATEST_SNAPSHOT" || exit 1 +verify_snapshot "$NEW_SNAPSHOT" || exit 1 if [ -n "$LAST_TRANSFERRED" ]; then verify_snapshot "$LAST_TRANSFERRED" || exit 1 fi -# Exit if no new snapshots to transfer -if [ "$LAST_TRANSFERRED" = "$LATEST_SNAPSHOT" ]; then - log "No new snapshots to transfer" - exit 0 -fi - # Create destination directory if it doesn't exist ssh "$REMOTE_HOST" "mkdir -p '$DEST_PATH'" # Perform the transfer if [ -z "$LAST_TRANSFERRED" ]; then # First time backup - full send - log "Performing full send of snapshot $LATEST_SNAPSHOT" - sudo btrfs send "$SNAPSHOT_PATH/$LATEST_SNAPSHOT/snapshot" | \ + log "Performing full send of snapshot $NEW_SNAPSHOT" + sudo btrfs send "$SNAPSHOT_PATH/$NEW_SNAPSHOT/snapshot" | \ pv --bytes | \ ssh "$REMOTE_HOST" "btrfs receive '$DEST_PATH'" && { - sudo echo "$LATEST_SNAPSHOT" | sudo tee "$STATE_FILE" + echo "$NEW_SNAPSHOT" | sudo tee "$STATE_FILE" log "Full send completed successfully" } || { log "ERROR: Full send failed" + sudo snapper -c "$SNAPPER_CONFIG" delete "$NEW_SNAPSHOT" exit 1 } else # Incremental send - log "Performing incremental send from $LAST_TRANSFERRED to $LATEST_SNAPSHOT" + log "Performing incremental send from $LAST_TRANSFERRED to $NEW_SNAPSHOT" sudo btrfs send -p "$SNAPSHOT_PATH/$LAST_TRANSFERRED/snapshot" \ - "$SNAPSHOT_PATH/$LATEST_SNAPSHOT/snapshot" | \ + "$SNAPSHOT_PATH/$NEW_SNAPSHOT/snapshot" | \ pv --bytes | \ ssh "$REMOTE_HOST" "btrfs receive '$DEST_PATH'" && { - sudo echo "$LATEST_SNAPSHOT" | sudo tee "$STATE_FILE" + echo "$NEW_SNAPSHOT" | sudo tee "$STATE_FILE" log "Incremental send completed successfully" } || { log "ERROR: Incremental send failed" + sudo snapper -c "$SNAPPER_CONFIG" delete "$NEW_SNAPSHOT" exit 1 } fi # Cleanup old snapshots if transfer was successful -cleanup_remote_snapshots +cleanup_snapshots # Verify remote snapshots log "Current remote snapshots:" get_remote_snapshots | sudo tee -a "$LOG_FILE" +log "Current local snapshots:" +get_local_snapshots | sudo tee -a "$LOG_FILE" + # Final verification if ! ssh "$REMOTE_HOST" "btrfs subvolume show '$DEST_PATH/snapshot'" &>/dev/null; then log "WARNING: Final verification failed" diff --git a/wallpapers b/wallpapers index 8ed82c9a..26552d8b 160000 --- a/wallpapers +++ b/wallpapers @@ -1 +1 @@ -Subproject commit 8ed82c9afaac6359cf4603196f7a5bd4b399a4b5 +Subproject commit 26552d8bade6fa39188ebf68e9ffa1a8dcd75108