Someone found my old ZFS snapshot script rather useful and wanted to improve it. Unfortunately I used the GPLv2 license in the original script. To accommodate my friend, I have re-released the snapshot script under the 2-clause BSD license. Feel free to use whichever license, 2-clause BSD or GPLv2, that suits your needs.

#!/bin/sh
# Shell script for creating periodic ZFS snapshots.

# Copyright © 2012, Trond Endrestøl <Trond.Endrestol@ximalas.info>
# All rights reserved.

# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met: 

# 1. Redistributions of source code must retain the above copyright notice, this
#    list of conditions and the following disclaimer. 
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution. 

# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# This script creates a monthly snapshot at midnight on the first day of every month.
# Should the snapshot exist, the old snapshot will be removed and recreated.

# Next, this script will create a daily snapshot at midnight,
# and hourly snapshots for the hours 01 to 23,
# and finally minutely snapshots for the minutes 01 to 59.
# Should the snapshot exist, the old snapshot will be removed and recreated.

# This script is supposed to be run by cron every minute.

# Example of invocation of this script from the system /etc/crontab:
# *     *       *       *       *       root    /path/to/create-periodic-zfs-snapshots.sh zpool/filesystem

# Example of invocation of this script from a user's crontab:
# *     *       *       *       *       /path/to/create-periodic-zfs-snapshots.sh zpool/filesystem

# Tested on FreeBSD/amd64 9.0-STABLE.

# A suitable PATH is nice to have, though most of the commands are given using absolute file names.
PATH=/bin:/sbin:/usr/bin:/usr/sbin
export PATH

# Make sure we have been given one, and only one, file system on the command line.
if [ "${#}" -ne 1 ]; then
  echo "Usage: ${0} zpool[/dataset]" >/dev/stderr;
  exit 1;
fi

# Make sure the file system exist.
if ! /sbin/zfs list -H -t filesystem ${1} >/dev/null 2>/dev/null; then
  echo "${0}: cannot find the file system ${1}" >/dev/stderr;
  exit 1;
fi

# I prefer to use English names on months and weekdays.
export        LANG=C
export      LC_ALL=${LANG}
export  LC_COLLATE=${LANG}
export    LC_CTYPE=${LANG}
export LC_MESSAGES=${LANG}
export LC_MONETARY=${LANG}
export  LC_NUMERIC=${LANG}
export     LC_TIME=${LANG}

# Extract the necessary details on the present.
month=`/bin/date +%B | /usr/bin/tr "[:upper:]" "[:lower:]"`
weekday=`/bin/date +%A | /usr/bin/tr "[:upper:]" "[:lower:]"`
day=`/bin/date +%d`
hour=`/bin/date +%H`
minute=`/bin/date +%M`

# The monthly snapshot will ALWAYS be created when appropriate.
if [ ${day} -eq 1 -a ${hour} -eq 0 -a ${minute} -eq 0 ]; then
  snapshot="${1}@${month}";

  # Destroy the monthly snapshot, if it exist.
  if /sbin/zfs list -H -t snapshot ${snapshot} >/dev/null 2>/dev/null; then
    /sbin/zfs destroy ${snapshot};
    zfs_destroy=${?};

    if [ ${zfs_destroy} -ne 0 ]; then
      exit ${zfs_destroy};
    fi;
  fi;

  # Create the monthly snapshot.
  /sbin/zfs snapshot ${snapshot};
  zfs_snapshot=${?};

  if [ ${zfs_snapshot} -ne 0 ]; then
    exit ${zfs_snapshot};
  fi;
fi

# Pick weekday, hour, or minute.
if [ ${hour} -eq 0 -a ${minute} -eq 0 ]; then
  snapshot="${1}@${weekday}";
elif [ ${minute} -eq 0 ]; then
  snapshot="${1}@hourly${hour}";
else
  snapshot="${1}@minute${minute}";
fi

# Destroy the snapshot, if it exist.
if /sbin/zfs list -H -t snapshot ${snapshot} >/dev/null 2>/dev/null; then
  /sbin/zfs destroy ${snapshot};
  zfs_destroy=${?};

  if [ ${zfs_destroy} -ne 0 ]; then
    exit ${zfs_destroy};
  fi;
fi

# Create the snapshot.
/sbin/zfs snapshot ${snapshot}

exit ${?}

# EOF of create-periodic-zfs-snapshots.sh.