I needed something like zfs-auto-snapshot written by Tim Foster but portable so it works on all systems that support ZFS. I reviewed a few scripts on github and was unhappy with what was out there so I decided to write my own.

With zbackup.rb you can define what to snapshot and how many rotation days you want to go back.

So say you want a month of snapshots:


/usr/bin/zbackup.rb iraidz/zWork 30

Simple, no? 😉

#!/usr/bin/env ruby

# Create snapshots for a 7 day rotation.
# ./zbackup.rb iraidz/zWork 7
#
# Add to crontab
# crontab -e
# 0 2 * * * /usr/bin/zbackup.rb iraidz/zWork 7

pool = ARGV[0]
days_back = ARGV[1].to_i

if pool.nil? or pool.empty?
  puts "\nDefine the pool you want to snapshot:"
  puts "\tex: zbackup.rb iraidz/zWork 7\n\n"
  exit 0
end

if days_back.nil? or days_back < 1 
  puts "\nDefine how many days for your rotation:"
  puts "\tex: zbackup.rb iraidz/zWork 7\n\n"
  exit 0
end

# response from zfs list
curr_snaps = `zfs list -t snapshot -o name`
# days back limit variable
date_back = Time.now - (86400*days_back)

curr_snaps.split(/\n/).each do |pline|
  if m = pline.match(/#{pool}\@([0-9]+)\-([0-9]+)\-([0-9]+)/)
    if date_back >= Time.local(m[1],m[2],m[3])
      `zfs destroy #{pline}`
    end
  end
end

# take snapshot for this run if needed.
month = Time.now.month
day = Time.now.day
year = Time.now.year
if curr_snaps !~ /#{pool}\@#{year}\-#{month}\-#{day}/
  `zfs snapshot -r #{pool}@#{year}-#{month}-#{day}`
end