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.

link|improve this question

feedback

3 Answers

up vote 4 down vote accepted

You may find something like this a little simpler

zfs list -t snapshot -o name -s name |grep ^tank@Auto | sed 1,15d | xargs -n 1 zfs destroy -r` 

Test it with ...|xargs -n 1 echo

link|improve this answer
I think this needs a sort -r before the sed command. sed seems to output the bottom of the list beyond the first 15 lines, which in the default sort is the most recent. Flipping the list means I get the oldest snapshots at the bottom. – growse Dec 14 '11 at 14:14
feedback

I may have solved this with some bash-fu.

 zfs list -t snapshot -o name | grep ^tank@AutoD- | sort -r | wc -l | xargs -n 1 expr -$NUM_TO_KEEP + | tr -d '\n' | xargs -0 -i bash -c "zfs list -t snapshot -o name | grep ^tank@AutoD- | sort -r | tail -n{} | sort |xargs -t -n 1 zfs destroy -r"

Wow. It feels so wrong.

link|improve this answer
feedback

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.

RETENTION=5
FS=tank1/test
SNAPNAME=daily-

zfs list -t snapshot -o name | grep ^$FS@${SNAPNAME} | sed -e :a -e "$d;N;2,${RETENTION}ba" -e 'P;D' | xargs -n 1 echo zfs destroy -r

Sources: http://sed.sourceforge.net/sed1line.txt

link|improve this answer
Upvote because anyone who can use sed like that deserves it. – growse 2 days ago
feedback

Your Answer

 
or
required, but never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.