3 exec >> /var/log/snap.log 2>&1
5 # This script makes a number of assumptions about how I am handling things.
6 # * filesystems are mounted on the directory with the same name. It is
7 # possible to mount them elsewhere in Solaris but I do not.
9 # * "tank" is mounted on /tank
10 # * "tank/home" is mounted on /tank/home
11 # * this script only handles one zfs filesystem, a wrapper should be created
13 # * this script handles all snapshots that are named in this format:
15 # * It ignores other snapshots
17 # This converts the YYYY-MM-DD.hh.mm format to an integer.
18 datetime_to_minutes() {
19 perl -n -e '/(\d+)-(\d+)-(\d+)\.(\d+)\.(\d+)/; print $1 * 527040 + $2 * 44640 + $3 * 1440 + $4 * 60 + $5,"\n"'
22 datetime_to_minutes2() {
23 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"'
26 # This number is the number of equally spaced snapshots that should exist over
27 # any given period in the past.
32 snapshotdir="/${filesystem}/.zfs/snapshot"
34 # Get the various components of the date
35 datetime=${ZFSDATETIME:-$(date +%Y-%m-%d.%H.%M)}
37 # Create the snapshot for this minute
38 echo "-I- Creating ${filesystem}@${datetime}"
39 zfs snapshot "${filesystem}@${datetime}"
41 lockdir="/tmp/zfs-admin-lock"
42 if ! mkdir "$lockdir" >/dev/null 2>&1; then
45 cleanup() { rm -rf "$lockdir"; }
48 minutes=$(echo $datetime | datetime_to_minutes)
51 snapshots=$(ls -d ${snapshotdir}/????-??-??.??.?? 2>/dev/null)
52 for snapshot in $snapshots; do
53 snapminutes=$(echo "$snapshot" | sed 's,.*/,,' | datetime_to_minutes)
54 snapminutes2=$(echo "$snapshot" | sed 's,.*/,,' | datetime_to_minutes2)
55 age=$((minutes - snapminutes))
58 if [ $age -lt $((window * numsnapshots)) ]; then
59 case $((snapminutes2 % window)) in
62 snapname=$(echo "$snapshot" |
63 sed 's,/\(.*\)/.zfs/snapshot/\(.*\),\1@\2,')
64 echo "-I- Destroying $snapname"
65 zfs destroy "$snapname"