From c8ba119a40437a080c0231f34c52c97aab29d5e3 Mon Sep 17 00:00:00 2001 From: "Carl N. Baldwin" Date: Wed, 20 Feb 2008 17:29:29 -0700 Subject: [PATCH] This script handled my initial snapshots on a single host. --- zfs-replicate | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100755 zfs-replicate diff --git a/zfs-replicate b/zfs-replicate new file mode 100755 index 0000000..20c480f --- /dev/null +++ b/zfs-replicate @@ -0,0 +1,104 @@ +#!/bin/bash + +: Usage: zfs-backup [filesystem] [destination_pool] + +tmpdir="/export/home/tmp" + +lockdir="/tmp/zfs-admin-lock" +if ! mkdir "$lockdir" >/dev/null 2>&1; then + echo >&2 "ZFS admin lock directory is present." + exit 1 +fi + +cleanup() { rm -rf "$lockdir"; } +trap cleanup EXIT + +fs=$1 +sourcepool=${1%%/*} +fsname=${1#*/} +destinationpool=$2 + +if ! zpool list -H "$sourcepool" >/dev/null 2>&1; then + echo >&2 "The source pool, '$sourcepool' doesn't seem to exist." + exit 1 +fi + +if ! zpool list -H "$destinationpool" >/dev/null 2>&1; then + echo >&2 "The destination pool, '$destinationpool' doesn't seem to exist." + exit 1 +fi + +if ! zfs list -H "$fs" >/dev/null 2>&1; then + echo >&2 "The source filesytem, '$fs' doesn't seem to exist." + exit 1 +fi + +printsnaps() { +sed 's,.*/,,' | awk '{print $1}' +} + +zfs list -rH -t snapshot $sourcepool/$fsname | printsnaps > /tmp/source-list +zfs list -rH -t snapshot $destinationpool/$fsname | printsnaps > /tmp/destination-list +diff -u /tmp/source-list /tmp/destination-list | grep -v '^+++' | awk '/^\+/ {print}' | sed "s,^\+,$destinationpool/," > /tmp/obsolete-snapshots +rm -f /tmp/source-list /tmp/destination-list + +echo >&2 "Removing obsolete backups from the destination pool" +for snapshot in $(cat /tmp/obsolete-snapshots); do + echo >&2 "Removing '$snapshot' from destination." + zfs destroy "$snapshot" +done + +echo >&2 "Rolling back to the most recent snapshot on the destination." +zfs rollback $(zfs list -rH -t snapshot $destinationpool/$fsname | awk '{snap=$1} END {print snap}') + +echo >&2 "Calculating the most recent common snapshot between the two filesystems." +common="" +if zfs list -H "$destinationpool/$fsname" >/dev/null 2>&1; then + for snap in $(zfs list -rH -t snapshot "$destinationpool/$fsname" | + sed 's,.*@,,' | awk '{print$1}'); do + if zfs list -rH -t snapshot "$fs" | sed 's,.*@,,' | awk '{print$1}' | grep "^${snap}$" >/dev/null 2>&1; then + common=$snap + fi + done +fi + +base=$common +foundcommon=false +if [ -z "$common" ]; then + foundcommon=true +fi + +for snap in $(zfs list -rH -t snapshot "$fs" | + sed 's,.*@,,' | awk '{print$1}'); do + if [ "$snap" = "$common" ]; then + foundcommon=true + continue + fi + + if $foundcommon; then + if [ -z "$base" ]; then + echo >&2 "Sending '$1/$snap'" + zfs send "$1@$snap" > $tmpdir/zfs.part + mv $tmpdir/zfs.part $tmpdir/zfs.data + zfs recv "$destinationpool/$fsname" < $tmpdir/zfs.data + rm -f $tmpdir/zfs.data + zfs set readonly=on "$destinationpool" + zfs set atime=off "$destinationpool" + zfs set sharenfs=off "$destinationpool" + zfs set mountpoint=legacy "$destinationpool" + zfs unmount "$destinationpool/$fsname" + zfs rollback "$destinationpool/$fsname@$snap" + else + echo >&2 "Sending '$1@$base' -> '$1/$snap'" + zfs send -i "$1@$base" "$1@$snap" > $tmpdir/zfs.part + mv $tmpdir/zfs.part $tmpdir/zfs.data + zfs recv "$destinationpool/$fsname" < $tmpdir/zfs.data + rm -f $tmpdir/zfs.data + # zfs unmount "$destinationpool/$fsname" + # zfs rollback "$destinationpool/$fsname@$snap" + fi + base=$snap + fi +done + +true -- 2.34.1