#!/bin/zsh

# Author: Aaron Toponce
# License: Public Domain
# Date: Mar 6, 2013
#
# Script to backup the snapshots of a ZFS filesystem to an offsite ZFS
# storage server using "zfs send" and "zfs receive". If put in crontab(5),
# it can execute after your "time sliding" snapshots, to make sure the
# latest snapshot is always offsite.
#
# This does require that your offsite ZFS pool is fully caught up with the
# exact snapshots as is on the source before this can be automated. After
# the offsite ZFS pool is a mirror of the src pool, then you can proceed
# with automating the script.

# Edit as necessary
BACKUP="offsite"    # pool name of offsite ZFS pool
ZFS="/sbin/zfs"     # full path to zfs(8) binary
ZPOOL="/sbin/zpool" # full path to zpool(8) binary

# Do not edit beneath here. Please.
SERVER="$(hostname -s)"
DSETS=($("$ZFS" list -H -o name -t filesystem -r pool))

for D in $DSETS; do
    POOL=$(echo "$D" | awk -F '@' '{split($1,a,"/"); print a[1]}')
    DSET=$(echo "$D" | awk -F '@' '{split($1,a,"/"); print a[2]}')

    if [ -z "$DSET" ]; then FS="$POOL" else FS="$POOL/$DSET" fi

    SNAPS=($("$ZFS" list -t snapshot -Ho name -S creation -r "$FS" | grep "$FS@"))
    SNAPS=(${(@)SNAPS:#*swap*}) # no need to worry about swap

    FREQ_SNAP=(${(M)SNAPS:#*frequent*})
    HOUR_SNAP=(${(M)SNAPS:#*hourly*})
    DALY_SNAP=(${(M)SNAPS:#*daily*})
    WEEK_SNAP=(${(M)SNAPS:#*weekly*})
    MNTH_SNAP=(${(M)SNAPS:#*monthly*})

    # FIXME: change "ssh -c arcfour server.example.com" as necessary
    "$ZFS" send -RI "$FREQ_SNAP[2]" "$FREQ_SNAP[1]" | ssh -c arcfour server.example.com "$ZFS recv -Fduv $BACKUP/$SERVER"
done


syntax highlighted by Code2HTML, v. 0.9.1