#!/usr/bin/env bash set -euxo pipefail # Parse arguments function help { echo "Usage: $0 [-h|-i] volume" echo "Backup BTRFS subvolume on rapido to razmo." echo echo "Arguments:" echo " volume: Name of the subvolume to backup" echo echo "Options:" echo " -h: Display this help message." echo " -i: Don't fail if the receiving subvolume doesn't exist." } init=false while getopts "hi" OPTION do case "$OPTION" in h) help exit 0 ;; i) init=true ;; ?) help exit 2 ;; esac done shift "$((OPTIND - 1))" if [ "$#" -ne 1 ] then help exit 2 fi volume="$1" # Assertions [ -d "/mnt/rapido/${volume}" ] [ -d "/mnt/rapido/${volume}.bkp" ] || "$init" [ ! -d "/mnt/rapido/${volume}.new" ] [ -d "/mnt/razmo/${volume}.bkp" ] || "$init" [ -d "/mnt/razmo/${volume}" ] || "$init" [ ! -d "/mnt/razmo/${volume}.new" ] [ ! -d "/mnt/razmo/${volume}.snapshots" ] # Taking a snapshot of the running subvolume btrfs subvolume snapshot -r "/mnt/rapido/${volume}" "/mnt/rapido/${volume}.new" # Sending (the difference with) the last backup to the backup disk function error_handler() { btrfs subvolume delete "/mnt/rapido/${volume}.new" || true btrfs subvolume delete "/mnt/razmo/${volume}.new" || true } trap error_handler ERR if [ -d "/mnt/rapido/${volume}.bkp" ] then btrfs send -p "/mnt/rapido/${volume}.bkp" "/mnt/rapido/${volume}.new" | btrfs receive /mnt/razmo else btrfs send "/mnt/rapido/${volume}.new" | btrfs receive /mnt/razmo fi trap - ERR # Removing old backups and putting the new one in place [ ! -d "/mnt/rapido/${volume}.bkp" ] || btrfs subvolume delete "/mnt/rapido/${volume}.bkp" mv "/mnt/rapido/${volume}.new" "/mnt/rapido/${volume}.bkp" [ ! -d "/mnt/razmo/${volume}.bkp" ] || btrfs subvolume delete "/mnt/razmo/${volume}.bkp" mv "/mnt/razmo/${volume}.new" "/mnt/razmo/${volume}.bkp" # Create a writeable clone in case we need to boot on the HDD # Needs to move away then back the .snapshots folder [ ! -d "/mnt/razmo/${volume}/.snapshots" ] || mv "/mnt/razmo/${volume}/.snapshots" "/mnt/razmo/${volume}.snapshots" [ ! -d "/mnt/razmo/${volume}" ] || btrfs subvolume delete "/mnt/razmo/${volume}" btrfs subvolume snapshot "/mnt/razmo/${volume}.bkp" "/mnt/razmo/${volume}" [ ! -d "/mnt/razmo/${volume}.snapshots" ] || mv "/mnt/razmo/${volume}.snapshots" "/mnt/razmo/${volume}/.snapshots" sync