Skip to content

Instantly share code, notes, and snippets.

@huafu
Created December 15, 2015 18:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save huafu/34e96b3c3c0f6abcf23e to your computer and use it in GitHub Desktop.
Save huafu/34e96b3c3c0f6abcf23e to your computer and use it in GitHub Desktop.
Backup of LVM logical volume by creating a gzip compressed image of temporary snapshot
#!/bin/bash
# usage:
# lvimg lv_dev [backup_path]
#
# lv_dev: path to the logical volume to backup
# backup_path: optional, base path of backups (default to /mnt/backups)
# config
DEFAULT_BACKUP_PATH="/mnt/backups"
LV_SNAPSHOT_NAME='lvimg-tmp-snapshot'
## -=-=-=-=-=| source |=-=-=-=-=-
LV="$1"
BACKUPS_PATH="${2:-$DEFAULT_BACKUP_PATH}"
# check if stdout is a terminal...
if [ -t 1 ]; then
# see if it supports colors...
ncolors=$(tput colors)
if test -n "$ncolors" && test $ncolors -ge 8; then
bold="$(tput bold)"
underline="$(tput smul)"
standout="$(tput smso)"
normal="$(tput sgr0)"
black="$(tput setaf 0)"
red="$(tput setaf 1)"
green="$(tput setaf 2)"
yellow="$(tput setaf 3)"
blue="$(tput setaf 4)"
magenta="$(tput setaf 5)"
cyan="$(tput setaf 6)"
white="$(tput setaf 7)"
fi
fi
function log() {
echo -e "$@"
}
function err() {
log " • ${red}${@}${normal}"
}
function info() {
log "\n• ${green}${@}${normal}"
}
function warn() {
log " • ${yellow}${@}${normal}"
}
function vg_for() {
lvs --noheadings -o vg_name "$1" 2> /dev/null | xargs
}
function lv_for() {
lvs --noheadings -o lv_name "$1" 2> /dev/null | xargs
}
function is_lv_path() {
if [ ! -z "$1" ] && [ -b $1 ]; then
if lvs --noheadings -o lv_name,vg_name "$1" &> /dev/null; then
return 0
fi
fi
return 1
}
function block_source() {
df --output=source "$1" 2> /dev/null | tail -1 | xargs
}
function is_same_file() {
if [ -z "$1" ] || [ -z "$2" ]; then
exit 1;
fi
f1=$(stat -L -c "%d:%i" "$1")
f2=$(stat -L -c "%d:%i" "$2")
if [ "$f1" == "$f2" ]; then
return 0
fi
return 1
}
# test if we are root
if [ $(id -u) != 0 ]; then
err "This script must be run as root"
exit 1
fi
# test if given arg is a path to a LV
if ! is_lv_path "$LV"; then
err "First argument must the logical volume path to backup"
exit 1
fi
# test if backup path is a valid directory
if [ -z "$BACKUPS_PATH" ] || [ ! -d "$BACKUPS_PATH" ]; then
err "Invalid backup back: $BACKUPS_PATH"
exit 1
fi
VG=$(vg_for "$LV")
LV=$(lv_for "$LV")
SNAPSHOT="${VG}/${LV_SNAPSHOT_NAME}"
# test if we are not already creating a snapshot on that VG already
if [ -e "/dev/${SNAPSHOT}" ]; then
err "/dev/${SNAPSHOT} exists, there might be another backup running"
exit 1
fi
# test if backup path exists and if it is not on the LV we're backing up
BACKUPS_DEV=$(block_source "$BACKUPS_PATH")
if is_same_file "$BACKUPS_DEV" "/dev/$VG/$LV"; then
err "Destination $BACKUPS_PATH is on the same block device ($BACKUPS_DEV) of the one to actually backup"
exit 1
fi
# create the snapshot
info "Creating a snapshot of $VG/$LV into $SNAPSHOT..."
lvcreate -L 2g -s -n "$LV_SNAPSHOT_NAME" "/dev/${VG}/${LV}"
if [ $? != 0 ]; then
exit 1
fi
# create the directory where to save the image
IMG_PATH=${BACKUPS_PATH}/$VG
IMG="${LV}@$(TZ=UTC date +'%Y-%m-%dT%H:%M:%S.000Z').img"
mkdir -p "$IMG_PATH"
if [ $? != 0 ]; then
err "Error creating the directory where to save the image"
exit 1
fi
# create the compressed image
IN="/dev/$SNAPSHOT"
OUT="$IMG_PATH/$IMG.gz"
info "Creating an image of the snapshot into $OUT..."
#echo dd if="$IN" of="$OUT" bs=2m
#pv < "$IN" > "$OUT"
pv -cN source "$IN" | GZIP=-1 gzip | pv -cN gzip > "$OUT"
if [ $? != 0 ]; then
err "Error creating the snapshot image"
exit 1
fi
# remove the snapshot
info "Removing snapshot $SNAPSHOT..."
lvremove -f "/dev/$SNAPSHOT"
SIZE=$(du -sh "$OUT" | cut -f 1)
info "Done creating image of $VG/$LV into $OUT ($SIZE)"
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment