btrbk/btrbk
2022-07-07 15:04:38 +02:00

182 lines
6.1 KiB
Bash
Executable file

#!/bin/bash
startDate=$(date +%s)
function bkRun {
local date=$(date +%Y-%m-%d)
local month=$(date +%Y-%m)
local bkSuffix=("${INCR[0]}" "${FULL[0]}")
local keepTime=("${INCR[1]}" "${FULL[1]}")
for i in ${!SUBVOLS[@]}; do
snapName=${VOLNAME[$i]}.$date
getSnap "$i"
if [[ -d "$SNAPDIR$snapName" && "$force" != true ]]; then
echo "backup already run today"
continue
else
btrfs subvolume snapshot -r ${SUBVOLS[$i]} $SNAPDIR$snapName
sync
fi
if [[ -d "$snapLast" && $1 = "incremental" ]]; then
btrfs send -p $snapLast $SNAPDIR$snapName | gpg --batch -er $PUBKEY -o - | rclone rcat $RCLONEDIR$month"-${INCR[0]}/"$snapName.pgp
else
btrfs send $SNAPDIR$snapName | gpg --batch -er $PUBKEY -o - | rclone rcat $RCLONEDIR$month"-${FULL[0]}/"$snapName.pgp
if [[ $1 = "full" ]]; then
for o in ${!bkSuffix[@]}; do
mapfile -t oldBk < <(rclone lsf $RCLONEDIR | grep ....-..-${bkSuffix[$o]} | head -n -${keepTime[$o]})
for n in ${!oldBk[@]}; do
rclone delete $RCLONEDIR${oldBk[$n]}
done
done
fi
fi
mapfile -t oldSnaps < <(ls -a $SNAPDIR | grep ${VOLNAME[$i]}.\....-..- | head -n -$KEEPLOCAL)
for snap in ${!oldSnaps[@]}; do
btrfs subvolume delete $SNAPDIR${oldSnaps[$snap]}
done
done
rclone copy /etc/btrbk.conf $RCLONEDIR"config/"
end
}
function runRestore {
echo "not implemented yet™"
exit 1
if [ -z ${rDate+x} ]; then
for o in ${!VOLNAME[@]}; do
if [[ "${VOLNAME[$o]}" = "${restoreVol}" ]]; then
getSnap "$o"
break
elif [[ ! "${VOLNAME[@]}" =~ "${restoreVol}" ]]; then
echo "Subvolume doesnt exist"
exit 1
fi
done
# mkdir /mnt/$BTRFSUUID
# mount -o subvolid=1 -U $BTRFSUUID /mnt/$BTRFSUUID
# btrfs subvolume delete /mnt/$BTRFSUUID/
fi
}
function runFullRestore {
read -r -p "Do You want to run rclone config?[y/N]: " rcloneConf
case "$rcloneConf" in
[yY]) rclone config;;
*) ;;
esac
echo "Specify the remote path with trailing slash [remote:/path/to/backupdir/]"
read -r -p "Dir: " rcloneDir
read -r -p "Import GPG key?[y/N]: " gpgtest
case "$gpgtest" in
[yY])
echo "Enter Path of your gpg public and secret key"
read -r -p "Publickey: " gpgPub
read -r -p "Secretkey: " gpgPriv
gpg --import $gpgPub
gpg --pinentry-mode loopback --import $gpgPriv;;
*) ;;
esac
if ! [ -e "/etc/btrbk.conf" ]; then
rclone copy $rcloneDir"config/btrbk.conf" "/etc/btrbk.conf"
fi
source /etc/btrbk.conf
local bkSuffix=("${INCR[0]}" "${FULL[0]}")
btrfs subvolume create $restoreDir"restore"
lastBkDate=$(rclone lsf "$rcloneDir" | grep ....-..-${FULL[0]} | tail -n -1 | sed "s/full\/$//")
for i in ${!bkSuffix[@]}; do
mapfile -t bkFile < <(rclone lsf "$rcloneDir$lastBkDate${bkSuffix[$i]}" 2>/dev/null)
for o in ${!bkFile[@]}; do
rclone rcat "$rcloneDir$lastBkDate${bkSuffix[$i]}/${bkFile[$o]}" | gpg --batch -d $PUBKEY -o - | btrfs receive $restoreDir"restore"
done
done
for i in ${!VOLNAME[@]}; do
newestSnap=$(ls -a $restoreDir"restore" | grep ${VOLNAME[$i]}.\....-..- | tail -n -1 )
btrfs subvolume snapshot $restoreDir"restore/"$newestSnap $restoreDir${VOLNAME[$i]}
done
}
function getSnap {
for i in $1; do
snapLast=$SNAPDIR${VOLNAME[$i]}.$(date -d "$date -1 day" +%Y-%m-%d)
if ! [[ -d "$snapLast" ]]; then
snapLast=$SNAPDIR$(ls -a $SNAPDIR | grep ${VOLNAME[$i]}.$(date -d "$date" +%Y-%m)- | tail -n 1)
fi
done
}
function testConf {
source /etc/btrbk.conf
if [ -z ${rDate+x} ]; then
if ! date -d "$rDate" > /dev/null 2>&1; then
echo "date is in wrong format: YYYY-MM-DD"
exit 1
fi
fi
if rclone ls $RCLONEDIR > /dev/null 2>&1; then
if gpg --list-key $PUBKEY > /dev/null 2>&1; then
if [ "$restore" = true ]; then
runRestore
elif [ "$backup" = true ]; then
testDate
fi
else
echo "pubkey wrong or not found exit code: $?"
exit 1
fi
else
echo "rclone dir wrong or not found exit code: $?"
exit 1
fi
}
function testDate {
if [ `date +%d` != "01" ]; then
bkRun "incremental"
else
bkRun "full"
fi
}
function end {
echo "backup finished in $(( ($(date +%s) - startDate) / 60 )) min"
}
function echoHelp {
echo "Usage: btrbk [options]"
echo "A script to automatically or manually backup your btrfs subvolumes."
echo "options:"
echo " -b, --backup runs backup manually if not already run today"
echo " -f, --force force backup to override today's backup"
echo " -d, --date=YYYY-MM-DD define a date from which to restore when using -r"
echo " -r, --restore=VOLNAME restores the latest snapshot of a given subvolume"
echo " -x, --full-restore=PATH this walks you through an complete config restore"
echo " and will restore the whole system to a given directory"
echo " -h, --help display this help and exit"
exit 1
}
options=$(getopt -l "backup,force,date::,restore::,full-restore::,help" -o "bfd::r::x::h" -- "$@")
eval set -- "$options"
while true; do
case $1 in
-b|--backup) backup=true; shift;;
-f|--force) force=true; shift;;
-d|--date) rDate="$2"; shift;;
-r|--restore) restore=true; restoreVol=$2; shift;;
-x|--full-restore) fullRestore=true; restoreDir=$2; shift;;
-h|--help) Help; shift; break;;
--) shift; break;;
\?) echo "error"; exit 1;;
esac
shift
done
if [ "$fullRestore" = true ]; then
runFullRestore
elif [ "$backup" = true ]; then
testConf
else
echoHelp
fi