From c248cb851182c868b0a5ef89d02f65ece4bf1ad3 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 1 Nov 2013 03:56:46 +0100 Subject: [PATCH] added a first version of my Btrfs snapshot backup script For usage details please consult the file header and https://btrfs.wiki.kernel.org/index.php/Incremental_Backup --- bash/backup-btrfs.sh | 93 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 bash/backup-btrfs.sh diff --git a/bash/backup-btrfs.sh b/bash/backup-btrfs.sh new file mode 100644 index 0000000..48fc98a --- /dev/null +++ b/bash/backup-btrfs.sh @@ -0,0 +1,93 @@ +#!/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 2013 Steffen Vogel + # @license http://www.gnu.org/licenses/gpl.txt GNU Public License + # @author Steffen Vogel + # @link http://www.steffenvogel.de + ## +## + # This script is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or + # any later version. + # + # This script is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this script. If not, see . + ## + +# TODO: delete old snapshots in destination fs +# TODO: print statistics of send | receive pipe (speed & size) + +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" +