diff options
-rw-r--r-- | byteback-snapshot | 38 |
1 files changed, 28 insertions, 10 deletions
diff --git a/byteback-snapshot b/byteback-snapshot index dfd216f..daf368b 100644 --- a/byteback-snapshot +++ b/byteback-snapshot @@ -115,14 +115,18 @@ class BackupDirectory snapshot_times_sorted end - # Returns the size of the last completed snapshot (runs du, maybe slow) + # Returns the size of the given snapshot (runs du, may be slow) # # Would much prefer to take advantage of this feature: # http://dustymabe.com/2013/09/22/btrfs-how-big-are-my-snapshots/ # but it's not currently in Debian/wheezy. # - def latest_snapshot_size - `du -s -b #{snapshot_path(snapshot_times.last)}`.to_i + def snapshot_size(time=snapshot_times.latest) + `du -s -b #{snapshot_path(time)}`.to_i + end + + def average_snapshot_size(number=10) + snapshot_times.sort[0..number].inject(0) { |time, total| snapshot_size(time) } / number end # Create a new snapshot of 'current' @@ -159,6 +163,7 @@ opts = Trollop::options do opt :snapshot, "Take a new snapshot" opt :prune, "Prune old backups" + :type => :string opt :list, "List backups (by 'age' or 'importance')", :type => :string @@ -179,16 +184,28 @@ error("--root not readable") unless File.directory?(@root) @backups = BackupDirectory.new(@root) +def get_snapshots_by(method) + if method == 'importance' + @backups.snapshot_times_by_importance.reverse # least important first + elsif method == 'age' + @backups.snapshot_times + else + raise ArgumentError.new("Unknown snapshot sort method #{method}") + end +end if @do_snapshot + last_snapshot_time = @backups.snapshots.last + error("Last snapshot was less than six hours ago") unless + !last_snapshot_time || + Time.now - @backups.snapshots.last >= 6*60*60 # FIXME: make configurable + verbose "Making new snapshot" @backups.new_snapshot! end if @do_list - list = @do_list == 'age' ? - @backups.snapshot_times : # oldest first - @backups.snapshot_times_by_importance.reverse # least important first + list = get_snapshots_by(@do_list) print "Backups in #{@root} by #{@do_list}:\n" list.each_with_index do |time, index| print "#{sprintf('% 3d',index)}: #{time}\n" @@ -196,16 +213,17 @@ if @do_list end if @do_prune - target_free_space = @backups.latest_snapshot_size + verbose "Counting last 10 backups" + target_free_space = 1.5 * @backups.average_snapshot_size(10) verbose "Want to ensure we have #{target_free_space}" if @backups.free >= target_free_space verbose "(we have #{@backups.free} so no action needed)" else - snapshot_times_by_importance = @backups.snapshot_times_by_importance + list = get_snapshots_by(@do_prune) - while @backups.free < target_free_space && !snapshot_times_by_importance.empty? - to_delete = snapshot_times_by_importance.pop + while @backups.free < target_free_space && !list.empty? + to_delete = list.pop verbose "Deleting #{to_delete}" @backups.delete_snapshot!(to_delete) verbose "Leaves us with #{@backups.free}" |