Last active
July 9, 2018 22:52
-
-
Save abma/48c2b6240476509158c30fbf9a8ccc78 to your computer and use it in GitHub Desktop.
Incremental backup to external drive using snapper and btrfs send/receive
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# James W. Barnett | |
# Takes snapshots of each snapper configuration. It then sends the snapshot to | |
# a location on an external drive. After the initial transfer, it does | |
# incremental snapshots on later calls. It's important not to delete the | |
# snapshot created on your system since that will be used to determine the | |
# difference for the next incremental snapshot. | |
# Can set the backup directory here, or in the snapper configuration file with | |
# EXT_BACKUP_LOCATION | |
declare -r mybackupdir="/media/abma/backup" | |
# You can set a snapper configuration to be excluded by setting EXT_BACKUP="no" | |
# in its snapper configuration file. | |
#-------------------------------------------------------- | |
# Don't modify anything below here | |
set -e | |
if [[ $EUID -ne 0 ]]; then | |
echo "Script must be run as root." | |
exit | |
fi | |
declare -r description="latest incremental backup" | |
# It's important not to change this userdata in the snapshots, since that's how | |
# we find the previous one. | |
declare -r userdata="extbackup=yes" | |
declare -r configs=$(find /etc/snapper/configs/* -printf '%f\t') | |
for x in $configs; do | |
unset EXT_BACKUP | |
unset EXT_BACKUP_LOCATION | |
source /etc/snapper/configs/$x | |
do_backup=${EXT_BACKUP:-"yes"} | |
if [[ $do_backup == "yes" ]]; then | |
echo "Creating backup from $x" | |
BACKUPDIR=${EXT_BACKUP_LOCATION:-"$mybackupdir"} | |
if [[ -z $BACKUPDIR ]]; then | |
echo "ERROR: External backup location not set!" | |
exit 1 | |
elif [[ ! -d $BACKUPDIR ]]; then | |
echo "ERROR: $BACKUPDIR is not a directory." | |
exit 1 | |
fi | |
old_number=$(snapper -c $x list -t single | awk '/'"$userdata"'/ {print $1}') | |
new_number="$(snapper -c $x create --print-number)" | |
sync | |
new_snapshot=$SUBVOLUME/.snapshots/$new_number/snapshot | |
new_info=$SUBVOLUME/.snapshots/$new_number/info.xml | |
backup_location=$BACKUPDIR/$x/$new_number/ | |
old_backup=$BACKUPDIR/$x/$old_number/snapshot | |
mkdir -p $backup_location | |
if [[ -z "$old_number" ]]; then | |
echo "Performing initial backup for snapper configuration '$x'. This could take awhile..." | |
btrfs send $new_snapshot | btrfs receive $backup_location | |
else | |
old_snapshot=$SUBVOLUME/.snapshots/$old_number/snapshot | |
# Sends the difference between the new snapshot and old snapshot to | |
# the backup location. Using the -c flag instead of -p tells it that | |
# there is an identical subvolume to the old snapshot at the | |
# receiving location where it can get its data. This helps speed up | |
# the transfer. | |
btrfs send -c $old_snapshot $new_snapshot | btrfs receive $backup_location | |
cp $new_info $backup_location | |
snapper -c $x delete $old_number | |
fi | |
# Tag new snapshot as the latest | |
snapper -v -c $x modify -d "$description" -u "$userdata" $new_number | |
fi | |
done | |
date > $HOME/.lastbackup |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment