Skip to content

Instantly share code, notes, and snippets.

@amirkdv
Last active October 31, 2023 07:58
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save amirkdv/12d6cedfbb437670961d to your computer and use it in GitHub Desktop.
Save amirkdv/12d6cedfbb437670961d to your computer and use it in GitHub Desktop.
Backup an LVM logical volume via Rsync
#!/bin/bash
# Backup an entire LVM logical volume via a snapshot LV and rsync
[[ $( whoami ) != 'root' ]] && echo "sudo please" && exit 1
set -o errexit
set -o nounset
# LVM logical volume to backup
lv=book01
# LVM Volume Group the LV belongs to
vg=/dev/shelf
# leave room for possible changes in original volume *while* backup is running
snap_size=1G
snap="$lv-snap"
snap_mnt_point=/mnt/$snap
stamp="$lv-$( date +%Y.%m.%d-%H.%M )"
# backup destination, can be local/remote path that rsync recognizes
backup_dst=/var/shelf/book03/backups
log_file=$backup_dst/$stamp/backup.log
# limit the bandwidth used by rsync
rsync_bw=50M
main() {
create_snapshot_lv
backup
cleanup
echo "Alrighty! keep up the good work!" >&2
}
create_snapshot_lv() {
echo "creating snapshot volume $snap with size: $snap_size" >&2
lvcreate --size $snap_size --snapshot --name "$snap" "$vg/$lv"
echo "mounting snapshot volume $snap to $snap_mnt_point" >&2
mkdir -p $snap_mnt_point
mount -o ro $vg/$snap $snap_mnt_point
}
backup() {
num_files=$( rsync --archive --itemize-changes --dry-run "$snap_mnt_point/" 2>/dev/null | wc -l )
mkdir -p "$backup_dst/$stamp"
echo "dumping contents of $snap_mnt_point to $backup_dst/$stamp; total numer of files: $num_files" >&2
count=0
touch "$log_file"
while read file; do
echo $file >> $log_file
count=$(( $count + 1 ))
file_display="$( echo $file | cut -c1-100 )"
count_display="[$count of $num_files files]"
# \r for carriage return; and \e[K (equivalently \033[K) for clearing the line
echo -ne "\r\e[K$count_display $file_display" >&2
done < <( rsync --archive --verbose --bwlimit=$rsync_bw "$snap_mnt_point/" "$backup_dst/$stamp/" )
}
cleanup() {
echo -e "\ncleaning up ..."
umount -l "$snap_mnt_point"
sleep 1s
rmdir "$snap_mnt_point"
# let lvremove prompt so you don't accidentally throw out an entire LV
lvremove $vg/$snap
}
trap cleanup SIGINT SIGTERM
main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment