From bd049d5f9671edd0a40787a9137dc5ba0c1f3078 Mon Sep 17 00:00:00 2001 From: "Carl N. Baldwin" Date: Sat, 9 Feb 2008 20:33:33 -0700 Subject: [PATCH 1/1] My original snapshot script --- snap.sh | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100755 snap.sh diff --git a/snap.sh b/snap.sh new file mode 100755 index 0000000..c5d2985 --- /dev/null +++ b/snap.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +exec >> /var/log/snap.log 2>&1 + +# This script makes a number of assumptions about how I am handling things. +# * filesystems are mounted on the directory with the same name. It is +# possible to mount them elsewhere in Solaris but I do not. +# * examples +# * "tank" is mounted on /tank +# * "tank/home" is mounted on /tank/home +# * this script only handles one zfs filesystem, a wrapper should be created +# to handle more +# * this script handles all snapshots that are named in this format: +# YYYY-MM-DD.hh.mm +# * It ignores other snapshots + +# This converts the YYYY-MM-DD.hh.mm format to an integer. +datetime_to_minutes() { + perl -n -e '/(\d+)-(\d+)-(\d+)\.(\d+)\.(\d+)/; print $1 * 527040 + $2 * 44640 + $3 * 1440 + $4 * 60 + $5,"\n"' +} + +datetime_to_minutes2() { + perl -n -e '/(\d+)-(\d+)-(\d+)\.(\d+)\.(\d+)/; $monthadj=int(($2-1)/3)-1; $minadj=int($5/15); $houradj=int($4/3); print $1 * 1048576 + ( $2 + $monthadj ) * 65536 + $3 * 2048 + ( $4 + $houradj ) * 64 + $5 + $minadj,"\n"' +} + +# This number is the number of equally spaced snapshots that should exist over +# any given period in the past. + +filesystem=$1 +numsnapshots=$2 + +snapshotdir="/${filesystem}/.zfs/snapshot" + +# Get the various components of the date +datetime=${ZFSDATETIME:-$(date +%Y-%m-%d.%H.%M)} + +# Create the snapshot for this minute +echo "-I- Creating ${filesystem}@${datetime}" +zfs snapshot "${filesystem}@${datetime}" + +lockdir="/tmp/zfs-admin-lock" +if ! mkdir "$lockdir" >/dev/null 2>&1; then + exit 0 +fi +cleanup() { rm -rf "$lockdir"; } +trap cleanup EXIT + +minutes=$(echo $datetime | datetime_to_minutes) + +# Trim them down +snapshots=$(ls -d ${snapshotdir}/????-??-??.??.?? 2>/dev/null) +for snapshot in $snapshots; do + snapminutes=$(echo "$snapshot" | sed 's,.*/,,' | datetime_to_minutes) + snapminutes2=$(echo "$snapshot" | sed 's,.*/,,' | datetime_to_minutes2) + age=$((minutes - snapminutes)) + window=1 + while true; do + if [ $age -lt $((window * numsnapshots)) ]; then + case $((snapminutes2 % window)) in + 0) ;; + *) + snapname=$(echo "$snapshot" | + sed 's,/\(.*\)/.zfs/snapshot/\(.*\),\1@\2,') + echo "-I- Destroying $snapname" + zfs destroy "$snapname" + ;; + esac + break + fi + window=$((window*2)) + done +done -- 2.34.1