How to Delete All but Last N ZFS Snapshots

snapshotsolariszfs

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.

Best Answer

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 with grep ^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.