snippets/bash/backup-btrfs.sh
2022-08-19 23:59:53 +02:00

78 lines
1.9 KiB
Bash
Executable file

#!/bin/bash
##
# Incremental backups with Btrfs snapshots
#
# This script does incremental backups of Btrfs subvolumes
# across filesystem boundaries as proposed in the Btrfs wiki:
# https://btrfs.wiki.kernel.org/index.php/Incremental_Backup
#
# It uses the 'btrfs send' and 'btrfs receive' commands.
# Its not intended for simple snapshots in a single filesystem enviroment.
#
# @copyright 2021, Steffen Vogel
# @license http://www.gnu.org/licenses/gpl.txt GNU Public License
# @author Steffen Vogel <post@steffenvogel.de>
# @link https://www.steffenvogel.de
##
# TODO: delete old snapshots in source and destination fs
function usage {
echo "Usage: $(basename $0) SOURCE [DEST]"
echo
echo " SOURCE a path to the subvolume to backup"
echo " DEST an optional path to the backup destination"
echo " only required for initialization"
exit 1
}
set -e
if [ $# -lt 1 ]; then
echo -e "missing source"
echo
usage
fi
SRC=$(readlink -f "$1")
if [ -h "$SRC/.backup/destination" ]; then
DEST=$(readlink -f "$SRC/.backup/destination")
elif [ $# -ne 2 ] ; then
echo -e "missing destination"
echo
usage
else
DEST=$(readlink -f $2)
mkdir -p "$SRC/.backup/"
mkdir -p "$DEST"
ln -sf "$DEST" "$SRC/.backup/destination"
ln -sf "$SRC" "$DEST/source"
fi
# name for the new snapshot
SNAPSHOT=$(date +%F_%H-%M-%S)
LATEST="$SRC/.backup/$SNAPSHOT"
# snapshot the current state
btrfs subvolume snapshot -r "$SRC" "$LATEST"
# send changes
if [ -h "$DEST/latest-source" ]; then
PREVIOUS=$(readlink -f "$DEST/latest-source")
btrfs send -p "$PREVIOUS" "$LATEST" | btrfs receive "$DEST"
else
btrfs send "$LATEST" | btrfs receive "$DEST"
fi
# delete old snapshot in source fs
if [ -n "$PREVIOUS" ]; then
btrfs subvolume delete "$PREVIOUS"
fi
# update links to last backup
ln -rsfT "$DEST/$SNAPSHOT" "$DEST/latest"
ln -sfT "$LATEST" "$DEST/latest-source"