SOLVED periodic snapshot task triggers ... ?

jjb2018

Dabbler
Joined
Aug 12, 2018
Messages
28
Hi folks,

I'm new to FreeNAS. I've been running a Linux machine at home for a few years now with ZoL, and have now build a new FreeNAS machine to use primarily for backup storage. I have this FreeNAS machine at my office so I might also tinker a bit with using it for VM image storage. At the moment I have an RSYNC task setup to run once a day to pull data from my main linux machine at home. And I also have a periodic snapshot task setup to snapshot the backup destination dataset 5 mins before the next RSYNC task starts. So the auto snapshots are essentially taking a snapshot of the result of the previous RSYNC task ... which hopefully completes before the auto snapshot occurs. But I'm relying on the RSYNC task completing before the snapshot it taken, and a don't want any snapshots taken if the RSYNC task is still running - I know it's unlikely that the RSYNC task will run for more than 23h55min, but it could happen. There is a disconnect between the RSYNC tasks and the Periodic Snapshot tasks.

So at this point my question is probably obvious - is there a way to configure a scheduled task (whether it's a cron task or rsync task, or whatever) to trigger a periodic snapshot task that has been pre-configured? I have configured the periodic snapshot task to keep for 1 month. I just need some way of configuring the RSYNC task to trigger the pre-configured snapshot task rather than the snapshot task being triggered on a time basis.

If somebody knows of a straightforward way of achieving this then please share. Otherwise how do I submit an enhancement request to the devs?

Cheers,
JB
 

Chris Moore

Hall of Famer
Joined
May 2, 2015
Messages
10,080
I know it's unlikely that the RSYNC task will run for more than 23h55min, but it could happen.
I had an rsync running for about 28 days one time (over a 10Gb link, local LAN) to initially load data onto a new server. How long it runs depends entirely on how much data there is to copy.
There is a disconnect between the RSYNC tasks and the Periodic Snapshot tasks.
There is no connection whatever between the two entirely unrelated processes.
I just need some way of configuring the RSYNC task to trigger the pre-configured snapshot task rather than the snapshot task being triggered on a time basis.
The snapshot configuration tool in FreeNAS basically creates a cron job that runs at a set time or interval. Sounds like you also have a cron job for rsync. They are not dependent on one another. You could create a script that does the rsync then creates a snapshot when the rsync is complete and have your scheduler initiate your script that does both things, one after the other. If you are going to do a script, it would make more sense to do a snapshot first because they are almost instantaneous. Still, you have no way to know if the rsync is actually done before you call rsync again if you have rsync running from a cron job. The scheduler doesn't check to see if the last call completed before it makes the call again. You could write a script for the scheduler to call and you could have your script check to see if rsync is still running and if it is it could exit without taking any action.
 

Chris Moore

Hall of Famer
Joined
May 2, 2015
Messages
10,080
If somebody knows of a straightforward way of achieving this then please share. Otherwise how do I submit an enhancement request to the devs?
Most of us would write the script. For example:

Github repository for FreeNAS scripts, including disk burnin
https://forums.freenas.org/index.ph...for-freenas-scripts-including-disk-burnin.28/

If you want to submit a ticket, go here and create an account:
https://redmine.ixsystems.com/projects/freenas

Then you can submit the ticket from within your running instance of FreeNAS. Here is the manual page:
http://doc.freenas.org/11/system.html#support

The username and password it wants there is the username and password to the redmine system.
 

jjb2018

Dabbler
Joined
Aug 12, 2018
Messages
28
Hi Chris - thanks for your time.
Here's a little more history of my setup ... My backup "solution" used to be a Raspberry Pi with a 4TB USB attached drive. This was running Arch Linux, like my main server at home does, and I was using RSYNC to do the backups. I had a daily cron job on the RPi to pull the data from the main server over ssh. Since I could not run ZFS on the RPi I was using the --link-dest option in RSYNC to do incrimental backups and each incrimental backup would just create a new folder named in YYYY-MM-DD format. The backup script (developed in the wee hours of many mornings!) had three other features in it:

1. It created/checked a PID file at the start to determine whether the previous rsync cron job had finished yet or not. I following this article to get this right https://bencane.com/2015/09/22/preventing-duplicate-cron-job-executions/

Here is the code for this:
Code:
PIDFILE=/mnt/tank/home/justin/scripts/RSYNC-Backup.pid
if [ -f $PIDFILE ]
then
  PID=$(cat $PIDFILE)
  ps -p $PID > /dev/null 2>&1
  if [ $? -eq 0 ]
  then
	echo "Process already running"
	exit 1
  else
	## Process not found assume not running
	echo $$ > $PIDFILE
	if [ $? -ne 0 ]
	then
	  echo "Could not create PID file"
	  exit 1
	fi
  fi
else
  echo $$ > $PIDFILE
  if [ $? -ne 0 ]
  then
	echo "Could not create PID file"
	exit 1
  fi
fi


2. After the RSYNC part of the script was complete it was then finding all backup folders older than 28 days and delete them, therefore only keeping 28 days worth of backups. Here is the code for that:
Code:
find $TRGROOT/ -maxdepth 1 -mtime +28 -regextype 'posix-minimal-basic' -type d ! -path $TRGROOT -regex '.*/20[0-9]\{2\}-[0-9][0-9]-[0-9][0-9]$' -exec rm -r {} +


3. It would email me at the start and finish of the backup (just an email with a subject containing the current date and time). So I would see that it had run and when it finished.

Now on the new FreeNAS backup server I could run my old script with only some minor tweaks, but I thought I would initially use the FreeNAS GUI as much as possible. So, I created an RSYNC task in the GUI, and the Periodic Snapshot (creating snapshots that expire after 1 month), to capture the incremental changes. So this pretty much replicated the functionality of my previous script, but without the email notifications.

So I have since replaced the the RSYNC task (setup through the GUI) with a CRON task which will run this new version of my previous script:
Code:
#!/bin/bash

PIDFILE=/mnt/tank/home/justin/scripts/RSYNC-Backup.pid
if [ -f $PIDFILE ]
then
  PID=$(cat $PIDFILE)
  ps -p $PID > /dev/null 2>&1
  if [ $? -eq 0 ]
  then
	echo "Process already running"
	exit 1
  else
	## Process not found assume not running
	echo $$ > $PIDFILE
	if [ $? -ne 0 ]
	then
	  echo "Could not create PID file"
	  exit 1
	fi
  fi
else
  echo $$ > $PIDFILE
  if [ $? -ne 0 ]
  then
	echo "Could not create PID file"
	exit 1
  fi
fi

SRC="/home/justin/"
TRG="/mnt/seagate"
FILTER="/mnt/tank/home/justin/scripts/RSYNC-Backup-Filter.txt"
LOGFILE="/mnt/tank/home/justin/scripts/rsync-logs/`date +%F`.log"

rsync -avhP -z --compress-level=2 \
--include-from=$FILTER \
--exclude-from=$FILTER \
--delete \
--log-file=$LOGFILE \
-e 'ssh -p 4444 -i /mnt/tank/home/justin/.ssh/id_rsa -o BatchMode=yes' \
justin@my-home-server.com:$SRC $TRG

printf "RSYNC Log file is "$LOGFILE"\n\n`head -n 10 $LOGFILE`\n\n*********************\n\n`tail -n 10 $LOGFILE`\n\n`zpool status seagate`" | mail -s "IXTREME backup report `date +%F`" my-email-address@emailsrus.com

rm $PIDFILE

exit


This gives me my emails back. This works well and will not run repeatedly if the previous cron task is still running, or even if the previous cron job was terminated abnormally. If it is terminated abnormally, and the PID file is left behind, then the next cron job will still run through as it checks the PID number recorded in the PID file. I still have the periodic snapshot task taking a snaphot a few minutes before the cron job starts. As I said in my previous message this where the disconnect is, that I don't like. I would like to see, in the GUI, an option in the cron / rsync task definition windows to trigger one of the periodic snapshot tasks which have been defined the periodic snapshot task part of the GUI. And an option in the periodic snapshot task to configure it to be run manually (or by trigger) only, or on a time schedule as it currently is.

I have been looking into whether I could get my backup script to take the snapshot but I don't know how I can manually create a snapshot, by cmd line, that will be automatically destroyed after x number of days. How does FreeNAS clear out expired snapshots? Is it just down to a strict and specific snapshot naming convention, or is there something more sophisticated going on to "register" snapshots that need to be destroyed in the future (like in a database or something).

Anyway, I'm relying on the GUI to do the expiring snapshots because I haven't figured out how to do that in my backup script.

Any suggestions are welcome!
 

kdragon75

Wizard
Joined
Aug 7, 2016
Messages
2,457
I would love to see "events" and "actions" in freenas. We could say "when event 'rsync' 'completes' do 'snapshot'".
 

rogerh

Guru
Joined
Apr 18, 2014
Messages
1,111
I have been looking into whether I could get my backup script to take the snapshot but I don't know how I can manually create a snapshot, by cmd line, that will be automatically destroyed after x number of days. How does FreeNAS clear out expired snapshots? Is it just down to a strict and specific snapshot naming convention, or is there something more sophisticated going on to "register" snapshots that need to be destroyed in the future (like in a database or something).

FreeNAS just uses the name it gives the snapshot. The name contains the date and time it was created and the desired duration it is to be kept. FreeNAS periodically examines all the snapshots and deletes those that are older than the desired duration. Interestingly, the replication task logs into the receiving server and sends any new snapshots and then deletes any snapshots on the receiving server that are no longer on the sending server. There are several ways for this to go wrong if the receiving zfs server is not running FreeNAS, but it sometimes works on zfsonlinux.
 

Chris Moore

Hall of Famer
Joined
May 2, 2015
Messages
10,080
I have been looking into whether I could get my backup script to take the snapshot but I don't know how I can manually create a snapshot,
This is the command I use to take a manual snapshot of the pool in one of my servers. zfs snapshot -r Irene@manual-23Sep2018
The zfs part is the program, the reset are parameters you are passing in. The snapshot part is pretty self explanatory, but -r if I recall correctly makes the snapshot recursive. The Irene part is the name of the pool being acted on. The @ tells the command that you are giving the name of the snapshot and the part after the @ could be what you want it to be, within reason.

Here is a refference for how to build the command: https://docs.oracle.com/cd/E19253-01/819-5461/gbcya/index.html
 

Chris Moore

Hall of Famer
Joined
May 2, 2015
Messages
10,080
PS. If you are manually creating snapshots from a script running through cron, you will need to manually destroy those snapshots when you don't want them any more.
 

Chris Moore

Hall of Famer
Joined
May 2, 2015
Messages
10,080
I would love to see "events" and "actions" in freenas. We could say "when event 'rsync' 'completes' do 'snapshot'".
Did you submit a feature request? With the new GUI they have build for 11.2, many features that would not have been possible before may be a possibility in the future.
 

jjb2018

Dabbler
Joined
Aug 12, 2018
Messages
28
I would love to see "events" and "actions" in freenas. We could say "when event 'rsync' 'completes' do 'snapshot'".
This is exactly what I have in mind. I can't imagine it would be very difficult in terms of coding - but I'm not a software developer so I can't say.

FreeNAS just uses the name it gives the snapshot. The name contains the date and time it was created and the desired duration it is to be kept. FreeNAS periodically examines all the snapshots and deletes those that are older than the desired duration. Interestingly, the replication task logs into the receiving server and sends any new snapshots and then deletes any snapshots on the receiving server that are no longer on the sending server. There are several ways for this to go wrong if the receiving zfs server is not running FreeNAS, but it sometimes works on zfsonlinux.

Roger - thanks for this. So you're saying that if I manually create a snapshot and follow the same naming convention used by the periodic snapshot tasks, that FreeNAS would find these and deal with them? I'll have to experiment with this I think.

@Chris Moore - thanks for the info. I've been running ZFS on linux on my Arch Linux server at home for a number of years now so I'm pretty comfortable with snapshots and other ZFS commands. If I can understand how FreeNAS automatically destroys snapshots when they "expire" then I'm sure I could manually create snapshots that follow the required naming convention (if it's all based on naming conventions that is).

Even if it is possible to do what I want by script, I still think this should be do-able in the GUI. My impression is that FreeNAS is supposed to be a GUI driven, set-and-forget, system.
Did you submit a feature request? With the new GUI they have build for 11.2, many features that would not have been possible before may be a possibility in the future.
I'll see if I can submit a feature request.
 

Chris Moore

Hall of Famer
Joined
May 2, 2015
Messages
10,080
(if it's all based on naming conventions that is).
I have not looked at the internals of the code, but FreeNAS does not delete manually created snapshots, so I think it keeps a list of the snapshots it creates and their associated time to live. I don't think you will be able to have FreeNAS auto-magically delete your snapshots that you create, you will need to create a method to handle that, if you want manual snapshots. I just use the automatic system from the GUI unless I have some special need for a snapshot.
 

rogerh

Guru
Joined
Apr 18, 2014
Messages
1,111
I have not looked at the internals of the code, but FreeNAS does not delete manually created snapshots, so I think it keeps a list of the snapshots it creates and their associated time to live. I don't think you will be able to have FreeNAS auto-magically delete your snapshots that you create, you will need to create a method to handle that, if you want manual snapshots. I just use the automatic system from the GUI unless I have some special need for a snapshot.


I think it will if you create a snapshot in between the planned snapshots on a dataset which is already the subject of a FreeNAS snapshot task, and follow the syntax exactly. I have tested this to a limited extent. You could perhaps use this to delete snapshots automatically by setting up a very infrequent and rapidly expiring FreeNAS snapshot task on the dataset you were interested in and thus getting your own snapshots automatically deleted on expiry, every five or one minute(s) I can't remember which. One would have to read the Python scripts to find out whether snapshots using the same syntax on another dataset were deleted. Or test it. I agree with you it is unlikely.

It certainly doesn't remove such expired snapshots from replication destination, I have tested this too, by having a replication task that succeeded in sending the snapshots but not in being informed that it had succeeded, and thus failed to delete that dataset's expired snapshots.
 

jjb2018

Dabbler
Joined
Aug 12, 2018
Messages
28
Well ... as I expected, it's no good for one member of a community to submit an idea for a new feature. Who know's what it will take but if anybody else thinks that the idea sketched out in this thread is worthy of support then please add your comments to the issue I logged here ...

https://redmine.ixsystems.com/issues/47844
 

rogerh

Guru
Joined
Apr 18, 2014
Messages
1,111
I doubt if the odd snapshot during the rsync task would do any harm, it would just not be a useful snapshot. Why not just set up a periodic snapshot task every 12 hours with a life of 1 week? If an rsync task fails or a backup needs to be used just look at the logs for when the last successful rsync task finished and choose the next snapshot after that for your recovery. The expense in storage of having 14 snapshots only 6 or so were potentially useful would probably not be that great compared with just having backups of, say, the last 7 rsync tasks anyway. But if you think you would spot a problem sooner then just a 2 day lifespan would make sure you had a snapshot of the previous rsync task, and you would only have to find space for 4 snapshots at least two of which would probably have zero space used because they were of the same successful rsync run.
 

jjb2018

Dabbler
Joined
Aug 12, 2018
Messages
28
I doubt if the odd snapshot during the rsync task would do any harm, it would just not be a useful snapshot.
I don't want any useless snapshots of partial backup data sitting on my server.
Why not just set up a periodic snapshot task every 12 hours with a life of 1 week? If an rsync task fails or a backup needs to be used just look at the logs for when the last successful rsync task finished and choose the next snapshot after that for your recovery. The expense in storage of having 14 snapshots only 6 or so were potentially useful would probably not be that great compared with just having backups of, say, the last 7 rsync tasks anyway. But if you think you would spot a problem sooner then just a 2 day lifespan would make sure you had a snapshot of the previous rsync task, and you would only have to find space for 4 snapshots at least two of which would probably have zero space used because they were of the same successful rsync run.
Thanks for offering your advice and ideas, it really is much appreciated. But this is a work-around to the problem, not a neat solution. If we had this capability to ensure that the RSYNC task completes, and then takes a good snapshot of the results (only one snapshot per RSYNC run is necessary), then this could provide a good clean solution.
I'm sure that even if this idea ever gets implemented then it will be a long while! In the meantime I have an idea to enhance my existing script to achieve automatic cleanup of old snapshots. I'll work on this and post what I come up with.
 

jjb2018

Dabbler
Joined
Aug 12, 2018
Messages
28
OK so here's what I've come up with for rolling snapshots with auto expiry / cleanup ...

#!/bin/bash

#NOTES:
#requires admin delagation if not run as root:
# zfs allow -u <user> mount,snapshot,destroy,userprop <dataset>

# what is the target dataset
DATASET="zfsdata/test"
# snapshots expire in 20 days
TTL="20d"

##### Create new snapshot
NEWSNAP=$DATASET@`date +%F-%H%M%S`
zfs snapshot $NEWSNAP

##### Set a User Property to record the expiry date and time for the snapshot in %s format
zfs set auto:expire=`date -v+$TTL +%s` $NEWSNAP

##### Destroy all snapshots for the dataset having an auto:expire property value less than or equal to date +%s
for OLDSNAP in `zfs list -t snapshot -r -H -o name $DATASET`
do
if [ `zfs list -t snapshot -r -H -o auto:expire $OLDSNAP` == '-' ]
then
continue
elif [ `zfs list -t snapshot -r -H -o auto:expire $OLDSNAP` -le `date +%s` ]
then
zfs destroy $OLDSNAP
fi
done
exit


So this can be run on it's own schedule, or tagged onto the end of an RSYNC script like this .... (using my own RSYNC script example) ....

#!/bin/bash

##### Prevent additional execution of the script if one is already running
PIDFILE=/mnt/tank/home/justin/scripts/RSYNC-Backup.pid
if [ -f $PIDFILE ]
then
PID=$(cat $PIDFILE)
ps -p $PID > /dev/null 2>&1
if [ $? -eq 0 ]
then
echo "Process already running"
exit 1
else
## Process not found assume not running
echo $$ > $PIDFILE
if [ $? -ne 0 ]
then
echo "Could not create PID file"
exit 1
fi
fi
else
echo $$ > $PIDFILE
if [ $? -ne 0 ]
then
echo "Could not create PID file"
exit 1
fi
fi

##### Set some vars
SRC="/home/justin/"
TRG="/mnt/seagate"
FILTER="/mnt/tank/home/justin/scripts/RSYNC-Backup-Filter.txt"
LOGFILE="/mnt/tank/home/justin/scripts/rsync-logs/`date +%F`.log"
# what is the target dataset
DATASET="zfsdata/test"
# snapshots expire in 20 days
TTL="20d"

##### Execute RSYNC backup
rsync -avhP -z --compress-level=2 \
--include-from=$FILTER \
--exclude-from=$FILTER \
--delete \
--log-file=$LOGFILE \
-e 'ssh -p 4444 -i /mnt/tank/home/justin/.ssh/id_rsa -o BatchMode=yes' \
justin@my-home-server.com:$SRC $TRG

##### If the previous RSYNC command does not complete successfully (exit code is not 0) then email a FAILED backup report and exit the script without continuing to take the snapshot of the backup.
if [ $? -ne 0 ]
then
printf "RSYNC Log file is "$LOGFILE"\n\n`head -n 10 $LOGFILE`\n\n*********************\n\n`tail -n 10 $LOGFILE`\n\n`zpool status seagate`" | mail -s "IXTREME backup report `date +%F`- FAILED" my-email-address@emailsrus.com
rm $PIDFILE
exit 1
fi

##### Send email report
printf "RSYNC Log file is "$LOGFILE"\n\n`head -n 10 $LOGFILE`\n\n*********************\n\n`tail -n 10 $LOGFILE`\n\n`zpool status seagate`" | mail -s "IXTREME backup report `date +%F` - SUCCESS" my-email-address@emailsrus.com

##### Create new snapshot
#NOTES:
#requires admin delagation if not run as root:
# zfs allow -u <user> mount,snapshot,destroy,userprop <dataset>
NEWSNAP=$DATASET@`date +%F-%H%M%S`
zfs snapshot $NEWSNAP

##### Set a User Property to record the expiry date and time for the snapshot in %s format
zfs set auto:expire=`date -v+$TTL +%s` $NEWSNAP

##### Destroy all snapshots for the dataset having an auto:expire property value less than or equal to date +%s
for OLDSNAP in `zfs list -t snapshot -r -H -o name $DATASET`
do
if [ `zfs list -t snapshot -r -H -o auto:expire $OLDSNAP` == '-' ]
then
continue
elif [ `zfs list -t snapshot -r -H -o auto:expire $OLDSNAP` -le `date +%s` ]
then
zfs destroy $OLDSNAP
fi
done

##### Delete PID file
rm $PIDFILE

exit


I've tested this on my linux machine and seems to work nicely. The above has been adjusted for BSD (some differences in the date command).

Any comments / suggestions for improvement are welcome!
 
Last edited:

Chris Moore

Hall of Famer
Joined
May 2, 2015
Messages
10,080
Any comments / suggestions for improvement are welcome!
I am writing some C++ tonight and don't have time to look in any detail, but on first glance, I like it. Thank you for contributing.
 

MSameer

Dabbler
Joined
Feb 12, 2019
Messages
14
OK so here's what I've come up with for rolling snapshots with auto expiry / cleanup ...

#!/bin/bash

#NOTES:
#requires admin delagation if not run as root:
# zfs allow -u <user> mount,snapshot,destroy,userprop <dataset>

# what is the target dataset
DATASET="zfsdata/test"
# snapshots expire in 20 days
TTL="20d"

##### Create new snapshot
NEWSNAP=$DATASET@`date +%F-%H%M%S`
zfs snapshot $NEWSNAP

##### Set a User Property to record the expiry date and time for the snapshot in %s format
zfs set auto:expire=`date -v+$TTL +%s` $NEWSNAP

##### Destroy all snapshots for the dataset having an auto:expire property value less than or equal to date +%s
for OLDSNAP in `zfs list -t snapshot -r -H -o name $DATASET`
do
if [ `zfs list -t snapshot -r -H -o auto:expire $OLDSNAP` == '-' ]
then
continue
elif [ `zfs list -t snapshot -r -H -o auto:expire $OLDSNAP` -le `date +%s` ]
then
zfs destroy $OLDSNAP
fi
done
exit


I've tested this on my linux machine and seems to work nicely. The above has been adjusted for BSD (some differences in the date command).

Any comments / suggestions for improvement are welcome!

I am using the script to manage snapshots for multiple pools.
I did a minor modification to allow passing the pool name and ttl via command line arguments to the script:
Code:
diff --git a/snapshot.sh b/snapshot.sh
index 6e048b7..b61e5e6 100755
--- a/snapshot.sh
+++ b/snapshot.sh
@@ -7,27 +7,28 @@
 # requires admin delagation if not run as root:
 # zfs allow -u <user> mount,snapshot,destroy,userprop <dataset>
 
-# what is the target dataset
-DATASET="zfsdata/test"
-# snapshots expire in 20 days
-TTL="20d"
+if [ $# -ne 2 ]; then
+    echo "Usage: $0 <dataset> <TTL>"
+    exit 1
+fi
 
-##### Create new snapshot
+DATASET=$1
+TTL=$2
+
+# Create new snapshot
 NEWSNAP=$DATASET@`date +%F-%H%M%S`
 zfs snapshot $NEWSNAP
 
-##### Set a User Property to record the expiry date and time for the snapshot in %s format
+# Set a User Property to record the expiry date and time for the snapshot in %s format
 zfs set auto:expire=`date -v+$TTL +%s` $NEWSNAP
 
-##### Destroy all snapshots for the dataset having an auto:expire property value less than or equal to date +%s
-for OLDSNAP in `zfs list -t snapshot -r -H -o name $DATASET`
-do
-    if [ `zfs list -t snapshot -r -H -o auto:expire $OLDSNAP` == '-' ]
-    then
-       continue
-    elif [ `zfs list -t snapshot -r -H -o auto:expire $OLDSNAP` -le `date +%s` ]
-    then
+# Destroy all snapshots for the dataset having an auto:expire property value less than
+# or equal to date +%s
+for OLDSNAP in `zfs list -t snapshot -r -H -o name $DATASET`; do
+    if [ `zfs list -t snapshot -r -H -o auto:expire $OLDSNAP` == '-' ]; then
+       echo "Skpping snapshot without expiry date $OLDSNAP"
+    elif [ `zfs list -t snapshot -r -H -o auto:expire $OLDSNAP` -le `date +%s` ]; then
+       echo "destroying expired snapshot $OLDSNAP"
        zfs destroy $OLDSNAP
     fi
 done
-exit


I also run my daily backup script under lockf. Using lockf allows me to easily prevent multiple executions of the same script in case it runs for more than a day.
 

jjb2018

Dabbler
Joined
Aug 12, 2018
Messages
28
I am using the script to manage snapshots for multiple pools.
I did a minor modification to allow passing the pool name and ttl via command line arguments to the script ...

...I also run my daily backup script under lockf. Using lockf allows me to easily prevent multiple executions of the same script in case it runs for more than a day.

I ended up doing the same thing actually - passing the dataset name and TTL as arguments to the script. I decided that I wanted to be able to perform rolling snapshots with different frequencies and expiry periods on different datasets. My rolling snapshot script currently looks like this ...
Code:
#!/bin/bash

DATASET=$1 #eg: "zfsdata/packages"
TTL=$2 # eg: "119 minutes" which is 2 hours minus 1 minute

##### Create new snapshot
#NOTES:
#requires admin delagation if not run as root:
#  zfs allow -u <user> mount,snapshot,destroy,userprop <dataset>
NEWSNAP=$DATASET@$(date +%F-%H%M%S)
zfs snapshot $NEWSNAP

##### Set a User Property to record the expiry date and time for the snapshot in %s format
zfs set auto:expire=$(date -v+$TTL +%s) $NEWSNAP

exit


I decided to split out the snapshot cleanup part to a separate script ...
Code:
#!/bin/bash
##### Destroy all snapshots for the dataset having an auto:expire property value less than or equal to date +%s
for OLDSNAP in $(zfs list -t snapshot -r -H -o name zfsdata)
do
        if [ $(zfs list -t snapshot -H -o auto:expire $OLDSNAP) == '-' ]
        then
                continue
        elif [ $(zfs list -t snapshot -H -o auto:expire $OLDSNAP) -le $(date +%s) ]
        then
                zfs destroy $OLDSNAP
        fi
done


The above is slightly modified to run in freeNAS. I'm actually running this on a Linux system where the line
Code:
zfs set auto:expire=$(date -v+$TTL +%s) $NEWSNAP

actually needs to be ...
Code:
zfs set auto:expire=$(date -d "+$TTL" +%s) $NEWSNAP


The reason I've split out the rolling snapshot cleanup script is because I wanted it to run on it's own schedule and more frequently. If it is only run when the snapshoting script is run then you have the possibility to have snapshots that have "auto:expired" hanging around on the system until the cleanup next occurs. So i have created multiple cron tasks to run the "rolling-snapshot.sh" script on various datasets with different "TTL" values. and I have another cron task which runs every 5 mins to run the "rolling-snapshot-cleanup.sh" script.
 
Top