1
0
Files
zfssnap/zfsbk.sh
2014-03-20 13:03:21 +01:00

118 lines
3.1 KiB
Bash
Executable File

#! /bin/sh
# change this to the name of your ZFS pool.
zpool="zroot"
# make a backup collection having 1 full and N-1 incremental backups.
# set to 1 to avoid incrementals and always take full dumps.
max_incremental=4
usage () {
echo "Usage:"
echo "zfsbk.sh <bkname> [numincr]"
echo "Takes & sends backup with given name. If snapshots with"
echo "this name exist, backup incrementally. Limit incremental"
echo "backup sequences to 'numincr' steps (default 1 = alw. full)."
echo
echo "Optional envvars:"
echo "UPLOAD_PATH upload generated backup to this path. scp:// or rsync://"
}
# first argument: name of backup set
if [ $# -lt 1 ]
then
usage
exit 1
fi
bkname=$1
if ! echo $bkname | grep -qiE '^[a-z0-9-]+$'
then
echo "Given bkname is invalid. Want alphanumeric and hyphens."
exit 1
fi
if echo "$2" | grep -qE '^[1-9][0-9]*$'
then
max_incremental=$2
fi
export PATH=$PATH:/usr/local/bin
# list snapshots by decreasing time. Arguments: [name] restrict listing to this tag
list_named_snaps () {
local bkname=$1
snapdir="/.zfs/snapshot"
for i in $snapdir/zbk-$bkname-*
do
test -e "$i" && (echo $i |sed "s@^$snapdir/@@")
done | sort -r
}
# remove all datasets for a given tag. Arguments: $1 -> bkname
reset_sequence () {
local bkname=$1
list_named_snaps $bkname | while read snapname
do
zfs destroy -r $zpool@$snapname
done
}
# take snapshot
#echo ./zfssnap.sh $bkname $max_incremental
if ! ./zfssnap.sh $bkname $max_incremental
then
echo "Error creating snapshot! Code $?"
exit 1
fi
# get label
num_snaps=`list_named_snaps $bkname | awk 'END {print NR}'`
label_latest=`list_named_snaps $bkname | awk NR==1`
# decide what to do based on how many snapshots were found
if [ $num_snaps -eq 0 ]
then
# no snapshots. Something's wrong
echo "Error, no snapshots found for $bkname!"
list_named_snaps $bkname
exit 1
elif [ $num_snaps -eq 1 ]
then
# first snapshot. Send full
bkfile="/backups/${label_latest}.dump"
#echo zfs send -R $zpool@$label_latest
zfs send -R $zpool@$label_latest 2>/dev/null > $bkfile
else
# n-th snapshot. Send incrementally
label_2ndlatest=`list_named_snaps $bkname | awk NR==2`
bkfile="/backups/${label_latest}--${label_2ndlatest}.dump"
#echo zfs send -i $label_2ndlatest -R $zpool@$label_latest
zfs send -i $label_2ndlatest -R $zpool@$label_latest 2>/dev/null > $bkfile
fi
if [ $num_snaps -eq $max_incremental ]
then
# finished the incremental sequence. Take full backup next time
echo "Sequence of $max_incremental increm steps complete. Resetting."
reset_sequence $bkname
fi
# upload backup to remote location
if [ "x$UPLOAD_PATH" != x ]
then
#echo "Archiving $bkfile remotely..."
if echo "$UPLOAD_PATH" | grep -qE '^rsync://'
then
rsync -qz $bkfile ${UPLOAD_PATH#rsync://}
elif echo "$UPLOAD_PATH" | grep -qE '^scp://'
then
scp -BCq $bkfile ${UPLOAD_PATH#scp://}
else
echo "UPLOAD_PATH not understood! '$UPLOAD_PATH'"
echo "Expecting rsync://.. or scp://.."
exit 1
fi
fi