Another piece of Bash forgery that automates a common administrative task: creating image-style (i.e. full) backups of logical volumes. The name is a combination of LVM, Snapshot and Backup.

The advantage compared to plain dd is that image contents are guaranteed to be consistent (at least as consistent as a power fault would leave disks), no matter how long the actual imaging process takes. By default lvsnackup uses LZO compression in order to benefit from zeroed blocks without slowing down too much.

Configuration

lvsnackup is configurable using the following environment variables:

  • CMD_COMPR: compression command (default: lzop -c)
  • COMPR_EXT: image file suffix (default: .lzo)
  • SNAP_SIZE: size of temporary change buffer (default: 1 GB)

Requirements

  • lvm (obviously)
  • lzop as default compressor
  • pv (Pipe Viewer, optional) for visual progress information

For Arch that's

$ pacman -S lvm lzop pv

Usage

$ lvsnackup /dev/vg0/root /mnt/backup/vg0-lvroot.img

Code

#!/bin/bash

# lvsnackup: Create LV Backups using LVM Snapshots
#   2015 Alexander Koch

# defaults
CMD_COMPR="${CMD_COMPR:-"lzop -c"}"
SNAP_SIZE="${SNAP_SIZE:-"1G"}"
COMPR_EXT="${COMPR_EXT:-".lzo"}"


if ! [ $# -eq 2 ]; then
    echo "error: invalid arguments."
    echo "usage: $0 VOLUME IMAGE"
    echo "  VOLUME:  path to logical volume to backup"
    echo "  IMAGE:   path to image, excl. compression suffix"
    exit 1
fi

SRC="$1"
DST="${2}${COMPR_EXT}"
SNAP="$(basename "$SRC")-snap"
SNAP_FULL="$(dirname "$SRC")/$SNAP"

if ! [ -e "$SRC" ]; then
    echo "error: invalid volume: '$SRC'."
    exit 1
fi

if ! [ -w "$DST" ] && ! [ -w "$(dirname "$DST")" ]; then
    echo "error: unable to write to '$DST'."
    exit 1
fi

ERR=0

# create snapshot volume
lvcreate -n "$SNAP" -L $SNAP_SIZE -s "$SRC" || exit 1

# compress contents to image
if tty -s && which pv &>/dev/null; then
    pv "$SNAP_FULL" | $CMD_COMPR > "$DST" || ERR=1
else
    $CMD_COMPR < "$SNAP_FULL" > "$DST" || ERR=1
fi

# destroy snapshot volume
lvremove -f "$SNAP_FULL" || ERR=1

exit $ERR

Update 2015-09-03: Fixed lvremove call

(updated on Thu 03 September 2015)