How to delete all but last [n] ZFS snapshots?
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 | grep ^tank@Auto | tac | tail -n +16 | xargs -n 1 zfs destroy -r
- Output the list of the snapshot (names only) with
zfs list -t snapshot -o name
- Filter to keep only the ones that match
tank@Auto
withgrep ^tank@Auto
- Reverse the list (previously sorted from oldest to newest) with
tac
- Limit output to the 16th oldest result and following with
tail -n +16
- Then destroy with
xargs -n 1 zfs destroy -vr
Deleting snapshots in reverse order is supposedly more efficient or sort in reverse order of creation.
zfs list -t snapshot -o name -S creation | grep ^tank@Auto | tail -n +16 | xargs -n 1 zfs destroy -vr
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.
zfs destroy zpool1/dataset@20160918%20161107
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.