snapshot is a simple Perl script used to manage ZFS snapshots. It is designed to be run from a cron job. It's configuration file is assumed to be snapShot.yaml in the same directory as the script. For those of us who prefer perl data structures, there is a script, confToYAML.pl which will take a perl definition of the configuration file and convert to yaml. Call it with confToYAML.pl < snapShot.cfg > snapShot.YAML A sample of snapShot.cfg is included. NOTICE: this uses the perl module yaml-tiny to read the configuration file Debian Based Systems: apt install libyaml-tiny-perl BSD Systems: cpan -i YAML::Tiny Every place that uses a frequency (ie, retention, frequency, slop) is expressed as a number of seconds. This should be an integer, optionally followed by a space and a unit. hour, day, week, month and year are acceptable units. == globals TESTING - if non-zero (true), will print the commands that would be executed to /tmp/snapshot slop - Number of seconds of slop allowed a cron job to determine if a new snapshot should be taken. listingkeys - Headers from the output of zfs list and zfs list -t snapshot, so we know which column is which There is no guarantee that cron and the timestamp embedded in the snapshot name will be exactly right. For example, if you were to run the cron job every hour, you may be off by a minute or two when deciding to create a new snapshot. 'slop' allows for this by saying "if we are slop seconds from needing a new snapshot, pretend we need it now". For a hourly cron job checking for daily snapshots, slop could be something like '1 hour' == datasets Basically, you choose one or more datasets to be managed. Each dataset can have three flags: retention: How long a to keep a snapshot after it was created frequency: How often to create a new snapshot recursive: Adds the -r command to both zfs snapshot and zfs destroy commands if set to non-zero The dataset key should be a regex, so escape all forward slashes and periods, ie for storage/iscsi.shares you would use storage\/iscsi\.shares The regex must match the entire string to keep from matching storage/iscsi.shares/local_stuff, etc... If you want to match child datasets, end the regex with '.*', ie storage\/iscsi\.shares.* See $config->{'datasets'} == snapshots Snapshots will be managed only if they match the parse regex, and will be created using the template string, which must be parsable by strftime. Care must be taken by the user to ensure parse and template match, and are correctly identified by parseFields. See $config{'snapshot'}.