I'm currently snapshotting my ZFS-based NAS nightly and weekly, a process that has saved my ass a few times. However, while the creation of the snapshot is automatic (from cron), the deletion of old snapshots is still a manual task. Obviously there's a risk that if I get hit by a bus, or the manual task isn't carried out, the NAS will run out of disk space.
Does anyone have any good ways / scripts they use to manage the number of snapshots stored on their ZFS systems? Ideally, I'd like a script that iterates through all the snapshots for a given ZFS filesystem and deletes all but the last n snapshots for that filesystem.
E.g. I've got two filesystems, one called tank
and another called sastank
. Snapshots are named with the date on which they were created: sastank@AutoD-2011-12-13
so a simple sort
command should list them in order. I'm looking to keep the last 2 week's worth of daily snapshots on tank
, but only the last two days worth of snapshots on sastank
.
You may find something like this a little simpler
zfs list -t snapshot -o name
tank@Auto
withgrep ^tank@Auto
tac
tail -n +16
xargs -n 1 zfs destroy -vr
Deleting snapshots in reverse order is supposedly more efficient or sort in reverse order of creation.
Test it with
...|xargs -n 1 echo
.This totally doesn't answer the question itself, but don't forget you can delete ranges of snapshots.
Would destroy all snapshots from "20160918" to "20161107" inclusive. Either end may be left blank, to mean "oldest" or "newest". So you could cook something up that figures out the "n" then destroy "...%n"..
Sorry to resurrect an old question.
More general case of getting most recent snapshot based on creation date, not by name.
zfs list -H -t snapshot -o name -S creation | head -1
Scoped to a specific filesystem name
TestOne
zfs list -H -t snapshot -o name -S creation -d1 TestOne | head -1
-H
:No header so that first line is a snapshot name-t snapshot
: List snapshots (list can list other things like pools and volumes)-o name
: Display the snapshot name property.-S creation
: CapitalS
denotes descending sort, based on creation time. This puts most recent snapshot as the first line.-d1 TestOne
: Says include children, which seems confusing but its because as far as this command is concerned, snapshots of TestOne are children. This will NOT list snapshots of volumes within TestOne such asTestOne/SubVol@someSnapshot
.| head -1
: Pipe to head and only return first line.growse's didn't work on OpenIndiana for me. It didn't understand -0 for xargs.
If using sort, be aware that it sorts alphabetically which may not be desired as you are probably wanting to find the most recent.
Here is code that will delete all but the last snapshots.
Remove the 'echo' to go live.
Sources: http://sed.sourceforge.net/sed1line.txt
You might also want to check out zfs-prune-snapshots.
It has a fairly robust time based mechanism for deleting snapshots, an example from the docs:
I may have solved this with some bash-fu.
Wow. It feels so wrong.
Just wanted to chime in on how I'm doing this on FreeBSD and OmniOS:
Get number of snapshots:
Subtract number you want to leave for n (e.g. 30 for a month of latest daily snapshots):
Note how I replaced
tail
withhead
to delete in order from oldest to newest, since there's notac
command on FreeBSDThat's it! Works great for me...
The path for head is needed on Solaris, but should work without the path on other distros.
Identify the latest two snapshots for a given dataset (creation, newest to oldest)
Identify ALL snapshots for a given dataset (creation, newest to oldest)
Remove latest snapshots from all set; creating a list of snapshots to delete.
Remove the old snapshots