-
Notifications
You must be signed in to change notification settings - Fork 0
Example: Backup a LVM snapshot using Borg
Daniel Rudolf edited this page Feb 22, 2019
·
4 revisions
- Borg
- LVM
bash
#!/bin/bash
set -eE -o pipefail
# repository path
REPOSITORY="/media/My-Backup-HDD/Borg"
# LVM logical volume
LVM_VOLUME="/dev/myvg/root"
MOUNTPOINT="/mnt"
# be verbose, otherwise output nothing (except errors)
BORG_CREATE_PARAMS=( -v --stats --show-rc )
BORG_DELETE_PARAMS=( -v --stats --show-rc )
BORG_PRUNE_PARAMS=( -v --list --stats --show-rc )
if tty --quiet; then
BORG_CREATE_PARAMS+=( --progress )
BORG_DELETE_PARAMS+=( --progress )
fi
if [ "$1" == "-q" ] || [ "$1" == "--quiet" ]; then
BORG_CREATE_PARAMS=()
BORG_DELETE_PARAMS=()
BORG_PRUNE_PARAMS=()
fi
# prepare traps
TRAPS=()
function trap_exit {
local INDEX=${#TRAPS[@]}
while [ $INDEX -gt 0 ]; do
((INDEX--))
eval "${TRAPS[$INDEX]}"
done
}
trap 'trap_exit' INT TERM EXIT
# create LVM snapshot
LVM_SNAPSHOT="$(dirname "$LVM_VOLUME")/snap"
lvcreate --extents 100%FREE --permission r --snapshot --name snap "$LVM_VOLUME" >&2
TRAPS+=( "lvremove --force \"$LVM_SNAPSHOT\" >&2" )
# mount LVM snapshot
mount -o ro "$LVM_SNAPSHOT" "$MOUNTPOINT"
TRAPS+=( "umount \"$MOUNTPOINT\"" )
cd "$MOUNTPOINT"
TRAPS+=( "cd \"$(dirname "$MOUNTPOINT")\"" )
echo
# prepare repository
if [ ! -e "$REPOSITORY" ]; then
mkdir "$REPOSITORY"
borg init --encryption=repokey "$REPOSITORY"
fi
if [ ! -d "$REPOSITORY" ]; then
echo "Invalid repository: $REPOSITORY" >&2
exit 1
fi
# create backup (ignore warnings)
BORG_CREATE_STATUS=0
borg create "${BORG_CREATE_PARAMS[@]}" \
--compression=lz4 \
--exclude-caches \
"$REPOSITORY"::'{hostname}-{now:%Y-%m-%dT%H:%M:%S}' \
. \
--exclude './lost+found' \
|| { BORG_CREATE_STATUS=$?; true; }
[ $BORG_CREATE_STATUS -lt 2 ] || exit $BORG_CREATE_STATUS
# remove checkpoints (ignore warnings)
BORG_DELETE_STATUS=0
if [ $BORG_CREATE_STATUS -eq 0 ]; then
BORG_CHECKPOINTS="$(borg list --short "$REPOSITORY" | grep -E '\.checkpoint(\.[0-9]+)?$' || true)"
if [ -n "$BORG_CHECKPOINTS" ]; then
xargs --max-args 1 --no-run-if-empty -I "%ARCHIVE%" -- \
borg delete "${BORG_DELETE_PARAMS[@]}" "$REPOSITORY"::"%ARCHIVE%" \
<<< "$BORG_CHECKPOINTS" \
|| { BORG_DELETE_STATUS=$?; true; }
[ $BORG_DELETE_STATUS -lt 2 ] || exit $BORG_DELETE_STATUS
fi
fi
# prune old backups (ignore warnings)
# keep everything within two days + 12 daily backups (= 2 weeks),
# 26 weekly backups (= 6 months), 24 monthly backups (= 2 years),
# 10 yearly backups
BORG_PRUNE_STATUS=0
borg prune "${BORG_PRUNE_PARAMS[@]}" \
"$REPOSITORY" --prefix '{hostname}-' \
--keep-within=2d --keep-daily=12 \
--keep-weekly=26 --keep-monthly=24 \
--keep-yearly=10 \
|| { BORG_PRUNE_STATUS=$?; true; }
[ $BORG_PRUNE_STATUS -lt 2 ] || exit $BORG_PRUNE_STATUS
if [ $BORG_CREATE_STATUS -eq 1 ] || [ $BORG_DELETE_STATUS -eq 1 ] || [ $BORG_PRUNE_STATUS -eq 1 ]; then
exit 254
fi