1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
#!/usr/bin/ruby
#
# Program to prune a byteback installation
$LOAD_PATH.unshift("/usr/lib/byteback")
require 'trollop'
require 'byteback'
require 'sys/filesystem'
include Byteback
include Byteback::Log
include Byteback::Util
opts = Trollop::options do
banner "Prune old backup directories to ensure there's enough space"
opt :minpercent, "Start prune when disk has less than this %age free",
:type => :integer,
:default => 5
opt :maxpercent, "Stop prune when disk has more than this %age free",
:type => :integer,
:default => 10
opt :list, "List backups in pruning order, no other action"
opt :prune, "Prune the next backup if necessary"
opt :order, "Order backups by 'age' or 'importance'",
:type => :string,
:default => "importance"
opt :verbose, "Show debugging messages"
end
@order = opts[:order]
@verbose = opts[:verbose]
@do_list = opts[:list]
@do_prune = opts[:prune]
@minpercent = opts[:minpercent]
@maxpercent = opts[:maxpercent]
fatal("Must specify one of --prune or --list") unless
(@do_prune || @do_list) &&
!(@do_prune && @do_list)
fatal("Must specify --order as 'age' or 'importance'") unless
@order == 'age' || @order == 'importance'
if BackupDirectory.all.empty?
fatal("No backup directories found, need to run byteback-snapshot")
end
@df_history = DiskFreeHistory.new(ENV['HOME'])
@df_history.new_reading!
# Don't do anything if we've not got two hours of readings
#
if @df_history.list.last.time - @df_history.list.first.time < 7200
warn("Not enough disc space history to make a decision")
exit 0
end
gradient_30m = @df_history.gradient(1800)
debug("Disc space gradient over 30m = #{gradient_30m}")
exit
# Check whether we should still be pruning
#
@free = @df_history.list.last.percent_free
PRUNING_FLAG = "#{ENV['HOME']}/.byteback.pruning"
if @free <= @minpercent && !File.exists?(PRUNING_FLAG)
warn("Starting prune, #{@free}% free (aiming for #{@maxpercent})")
File.write(PRUNING_FLAG,"")
elsif @free >= @maxpercent && File.exists?(PRUNING_FLAG)
warn("Stopping prune, #{@free}% free")
File.unlink(PRUNING_FLAG)
elsif File.exists?(PRUNING_FLAG)
warn("Continuing prune, #{@free}% free (aiming for #{@maxpercent})")
end
def snapshots_in_order
list = BackupDirectory.all_snapshots
if list.empty?
warn("Couldn't find any snapshots (yet?)")
end
if @order == 'importance'
Snapshot.sort_by_importance(list)
elsif @order == 'age'
list.sort.reverse
else
raise ArgumentError.new("Unknown snapshot sort method #{method}")
end
end
snapshots = snapshots_in_order
if @do_list
print "Backups by #{@order}:\n"
snapshots.each_with_index do |snapshot, index|
print "#{sprintf('% 3d',index)}: #{snapshot.path}\n"
end
end
exit 0 unless File.exists?(PRUNING_FLAG) && @do_prune
exit 0 if gradient_30m != 0
info("Deleting #{snapshots.last.path}")
log_system("sudo btrfs subvolume delete #{snapshots.last.path}")
|