Skip to content

Instantly share code, notes, and snippets.

@sumikawa
Created January 13, 2011 08:51
Show Gist options
  • Save sumikawa/777602 to your computer and use it in GitHub Desktop.
Save sumikawa/777602 to your computer and use it in GitHub Desktop.
snapshot-clean: cleanup old snapshot for zfs
#!/usr/local/bin/ruby18
#
# snapshot-clean: cleanup old snapshot for zfs
#
# Usage:
# snapshot-clean
#
# Copyright(C) 2010 Munechika Sumikawa <[email protected]>, All rights reserved.
# This is free software with ABSOLUTELY NO WARRANTY.
#
# This program was derived from pdumpfs-clean
# Copyright (C) 2003 Taku YASUI <[email protected]>
#
# You can redistribute it and/or modify it under the terms of
# the GNU General Public License version 2.
#
require 'getoptlong'
require 'date'
require 'ftools'
DEFAULT = { 'year' => 2,
'month' => 6,
'week' => 6,
'day' => 7 }
def parse_options
options = Hash.new
parser = GetoptLong.new
parser.set_options(['--help', '-h', GetoptLong::NO_ARGUMENT],
['--no-act', '-n', GetoptLong::NO_ARGUMENT],
['--verbose', '-v', GetoptLong::NO_ARGUMENT],
['--version', '-V', GetoptLong::NO_ARGUMENT],
['--keep', '-k', GetoptLong::REQUIRED_ARGUMENT])
parser.each_option {|name, arg|
options[name.sub(/^--/, "")] = arg
}
show_version if options['version']
show_usage if options['help']
return options
end
def parse_keep(keep)
ch_tables = { 'year' => /(\d+)Y/,
'month' => /(\d+)M/,
'week' => /(\d+)W/,
'day' => /(\d+)D/ }
ret = {}
ch_tables.each do |key, regex|
ret[key] = DEFAULT[key]
ret[key] = $1.to_i if ( regex.match(keep) )
ret[key] -= 1
end
return ret
end
def create_keepdirs(keep)
nowdate = Date.new(Time.now.year, Time.now.month, Time.now.day)
ret = []
# year
keep['year'].downto(0) do |i|
ret.push("#{Time.now.year-i}0101")
end
# month
keep['month'].downto(0) do |i|
date = nowdate << i
ret.push("#{date.year}#{sprintf("%02d", date.month)}01")
end
# week
keep['week'].downto(0) do |i|
date = nowdate - nowdate.cwday - 7 * i
ret.push("#{date.year}#{sprintf("%02d", date.month)}#{sprintf("%02d", date.day)}")
end
# day
keep['day'].downto(0) do |i|
date = nowdate - i
ret.push("#{date.year}#{sprintf("%02d", date.month)}#{sprintf("%02d", date.day)}")
end
ret.sort.uniq
end
def show_usage
print <<_EOT
Usage: snapshot-clean [OPTIONS]
OPTIONS:
--help, -h: show this help
--keep KEEPARGS, -k: use KEEPARGS to decide delete directories
--no-act, -n: run command but don't do it
--verbose, -v: verbose output
--version, -V: show software version
KEEPARGS: [digitY][digitM][digitW][digitD]
ex: --keep 2Y6M6W7D (2years, 6months, 6weeks, 7days, default)
_EOT
exit
end
def show_version
print <<_EOT
snapshot-clean
Copyright (C) 2010 Munechika Sumikawa <[email protected]>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.
This program was derived from pdumpfs-clean
Copyright (C) 2003 Taku YASUI <[email protected]>
_EOT
exit
end
def main
opts = parse_options
keepdirs = create_keepdirs(parse_keep(opts['keep']))
keeped = []
open "| /sbin/zfs list -t snapshot | awk '{print $1}' | grep -v '^NAME'" do |snapshot|
snapshot.each_line do |line|
line =~ /([\w\/]+)@([0-9][0-9][0-9][0-9][0-1][0-9][0-3][0-9])/
if ( $2 == nil or keepdirs.index($2))
keeped.push(line)
next
end
print "Deleting ", line.chop, " ..." if ( opts['verbose'] )
system('/sbin/zfs', 'destroy', line.chop) if ( ! opts['no-act'] )
print " done.\n" if ( opts['verbose'] )
end
end
if ( opts['verbose'] )
puts "Keep snapshots:"
keeped.each do |dir|
puts dir
end
end
end
main if __FILE__ == $0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment