Created
December 15, 2015 18:46
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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