Created
May 13, 2011 09:37
-
-
Save sarva/970260 to your computer and use it in GitHub Desktop.
Incremental BTRFS backups
This file contains hidden or 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 | |
# | |
# Sync data using rsync to a backup BTRFS fs subvolume and create | |
# incremental revolving snapshots | |
# | |
# Setting the -c option will setup crontab to continue running the | |
# backup at the set granularity (default daily) | |
# | |
# Install: | |
# | |
# cd /usr/local/bin | |
# wget https://gist.github.com/raw/970260/btrfs-backup.sh | |
# chmod 755 btrfs-backup.sh | |
# | |
# Show usage: | |
# | |
# btrfs-backup.sh -h | |
# | |
usage { | |
cat << EOF | |
usage: $0 [options] /path/to/backup /path/to/btrfs/volume subvol-name | |
Run / setup incremental backups to a BTRFS volume | |
OPTIONS: | |
-h Show this message | |
-g Granularity for increments. OPTIONS: hour, day, week, month DEFAULT: day. Use with -c will setup an appropriate crontab | |
-i Number of increments to save. DEFAULT: 7. -g hour -i 24 would save 24 hourly snapshots before overwriting old snapshots | |
-c Setup crontab job with current settings | |
-l Log file to append backup/snapshot log to. | |
-s Sleep mode. Unmount and put the BTRFS device to sleep after backup. Requires the volume to be setup in /etc/fstab | |
-v Verbose rsync | |
EOF | |
} | |
DX=day | |
INC=7 | |
CRON=false | |
SUBVOL= | |
LOG= | |
SLEEP= | |
VERBOSE=">/dev/null" | |
while getopts “hcvsg:i:l:” OPTION | |
do | |
case $OPTION in | |
h) | |
usage | |
exit 1 | |
;; | |
c) | |
CRON=true | |
;; | |
v) | |
VERBOSE="" | |
;; | |
s) | |
SLEEP=true | |
;; | |
g) | |
DX=$OPTARG | |
;; | |
i) | |
INC=$OPTARG | |
;; | |
l) | |
LOG=$OPTARG | |
;; | |
?) | |
usage | |
exit | |
;; | |
esac | |
done | |
if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then | |
usage | |
exit 1 | |
fi | |
function snapshot { | |
# delete old snapshot | |
if [ -d $1/$2-$3 ] | |
then | |
btrfsctl -D $2-$3 $1 $VERBOSE | |
fi | |
btrfsctl -s $1/$2-$3 $1/$2 $VERBOSE | |
if [ ! -z "$LOG" ]; then | |
echo "snapshot $2-$3: `date`" >> $LOG | |
fi | |
} | |
# find the appropriate absolute timestamp depending on granularity. day=daystamp, hour=hourstamp etc | |
# timestamp forever increase with time so are useful for ensuring increments can loop over each other | |
case $DX in | |
hour) | |
dx=60*60 | |
;; | |
day) | |
dx=60*60*24 | |
;; | |
week) | |
dx=60*60*24*7 | |
;; | |
?) | |
echo "Invalid granularity, only hour, day, week are supported" | |
exit 1 | |
;; | |
esac | |
# If sleep is specified, try and mount the volume first. | |
# Otherwise it should already be mounted | |
$SLEEP && | |
#setup sleep | |
(mount $2 && | |
DEV=`mount | grep "$2 type btrfs" | awk '{print $1}'`) || | |
# without sleep | |
(test -d $2/$3 && | |
mount | grep "$2 type btrfs" >/dev/null) | |
if [ $? -ne 1 ]; then | |
$SLEEP && | |
echo "Unable to mount BTRFS volume or it does not appear to be BTRFS. Make sure it is setup in /etc/fstab" || | |
echo "$2 does not appear to be a mounted BTRFS volume. It must be the parent BTRFS volume and not a subvolume. Use -s to set subvolumes" | |
exit 1 | |
fi | |
if [ ! -d $1 ] && [ ! -f $1 ]; then | |
echo "$1 does not exist" | |
fi | |
# rsync into BTRFS volume | |
rsync -va --progress --numeric-ids --delete-before --ignore-errors --partial --inplace --sparse $1/ $2/${3/%\//} $VERBOSE | |
# the granularity-adjusted timestamp value | |
((ts=`date +%s`/$dx)) | |
# snapshot dir | |
# TODO provide option to save snapshots into a different directory | |
((num=$ts%$INC)) | |
snapshot $2 $3 $num | |
# unmount and put to sleep | |
$SLEEP && | |
umount $2 $&& | |
hdparm -Y $DEV $VERBOSE | |
# setup a crontab entry for this backup job | |
if $CRON; then | |
[ $DX == "hour" ] && HOUR="*" || HOUR="0" | |
[ $DX == "week" ] && WEEK="0" || WEEK="*" | |
CMD="$0 -g $DX -i $INC `[ ! -z "$LOG ] && echo "-l $LOG"` `$SLEEP && echo "-s"` $1 $2 $3" | |
echo "`crontab -l`"$'\n'"0 $HOUR * * $WEEK $CMD" | crontab | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment