smarbs 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +23 -0
- data/History.txt +3 -0
- data/Manifest.txt +28 -0
- data/README.txt +88 -0
- data/Rakefile +10 -0
- data/bin/smarbs +11 -0
- data/lib/backup.rb +275 -0
- data/lib/data/configuration.txt +209 -0
- data/lib/data/iconblue.png +0 -0
- data/lib/data/icongreen.png +0 -0
- data/lib/data/iconred.png +0 -0
- data/lib/data/intro.txt +16 -0
- data/lib/data/outro.txt +15 -0
- data/lib/helpers.rb +438 -0
- data/lib/log.rb +214 -0
- data/lib/script.rb +217 -0
- data/lib/smarbs.rb +5 -0
- data/lib/syslog.rb +98 -0
- data/lib/types.rb +172 -0
- data/test/smarbs_test.rb +114 -0
- data/test/test_backup.rb +171 -0
- data/test/test_helpers.rb +500 -0
- data/test/test_log.rb +128 -0
- data/test/test_script.rb +118 -0
- data/test/test_smarbs.rb +131 -0
- data/test/test_smarbs_test.rb +76 -0
- data/test/test_suite.rb +11 -0
- data/test/test_types.rb +141 -0
- metadata +107 -0
data/.autotest
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'autotest/restart'
|
4
|
+
|
5
|
+
# Autotest.add_hook :initialize do |at|
|
6
|
+
# at.extra_files << "../some/external/dependency.rb"
|
7
|
+
#
|
8
|
+
# at.libs << ":../some/external"
|
9
|
+
#
|
10
|
+
# at.add_exception 'vendor'
|
11
|
+
#
|
12
|
+
# at.add_mapping(/dependency.rb/) do |f, _|
|
13
|
+
# at.files_matching(/test_.*rb$/)
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# %w(TestA TestB).each do |klass|
|
17
|
+
# at.extra_class_map[klass] = "test/test_misc.rb"
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
|
21
|
+
# Autotest.add_hook :run_command do |at|
|
22
|
+
# system "rake build"
|
23
|
+
# end
|
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
.autotest
|
2
|
+
History.txt
|
3
|
+
Manifest.txt
|
4
|
+
README.txt
|
5
|
+
Rakefile
|
6
|
+
bin/smarbs
|
7
|
+
lib/backup.rb
|
8
|
+
lib/data/configuration.txt
|
9
|
+
lib/data/iconblue.png
|
10
|
+
lib/data/icongreen.png
|
11
|
+
lib/data/iconred.png
|
12
|
+
lib/data/intro.txt
|
13
|
+
lib/data/outro.txt
|
14
|
+
lib/helpers.rb
|
15
|
+
lib/log.rb
|
16
|
+
lib/script.rb
|
17
|
+
lib/smarbs.rb
|
18
|
+
lib/syslog.rb
|
19
|
+
lib/types.rb
|
20
|
+
test/smarbs_test.rb
|
21
|
+
test/test_backup.rb
|
22
|
+
test/test_helpers.rb
|
23
|
+
test/test_log.rb
|
24
|
+
test/test_script.rb
|
25
|
+
test/test_smarbs.rb
|
26
|
+
test/test_smarbs_test.rb
|
27
|
+
test/test_suite.rb
|
28
|
+
test/test_types.rb
|
data/README.txt
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
= smarbs
|
2
|
+
|
3
|
+
* http://smarbs.sourceforge.net
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
smarbs is a backup script written in ruby capable of doing intelligent and
|
8
|
+
automated backups using rsync.
|
9
|
+
|
10
|
+
== FEATURES/PROBLEMS:
|
11
|
+
|
12
|
+
Smarbs was designed to be
|
13
|
+
|
14
|
+
* fast
|
15
|
+
* incremental
|
16
|
+
* able to take full snapshots
|
17
|
+
* space managing
|
18
|
+
* able to handle several sources
|
19
|
+
* automated
|
20
|
+
|
21
|
+
== SYNOPSIS:
|
22
|
+
|
23
|
+
Run smarbs --help to see what options you have. The configfiles are stored
|
24
|
+
in the directory /etc/smarbs or ~/.smarbs, if not executed as root.
|
25
|
+
|
26
|
+
= Syslog
|
27
|
+
|
28
|
+
Smarbs can log to syslog instead of directly to file. Note, you
|
29
|
+
should only enable this feature if you know what you are doing, and
|
30
|
+
have root access.
|
31
|
+
|
32
|
+
Example configuration for syslog-ng, this will log everything "smarbs"
|
33
|
+
into separate file.
|
34
|
+
|
35
|
+
destination smarbs { file("/var/log/smarbs.log"
|
36
|
+
template("$FULLDATE [$LEVEL] $MSG\n")
|
37
|
+
template_escape(no) );
|
38
|
+
};
|
39
|
+
filter f_smarbs { program(smarbs); };
|
40
|
+
log { source(src); filter(f_smarbs); destination(smarbs); };
|
41
|
+
|
42
|
+
To filter out some less important information, try:
|
43
|
+
|
44
|
+
filter f_smarbs { program(smarbs) and level(notice..err); };
|
45
|
+
|
46
|
+
Also, if you put $ISODATE there instead of $FULLDATE, you will get
|
47
|
+
date in ISO-standard format.
|
48
|
+
|
49
|
+
== REQUIREMENTS:
|
50
|
+
|
51
|
+
* Ruby 1.9.1
|
52
|
+
* rsync
|
53
|
+
* standard unix tools (du, df, ...)
|
54
|
+
* optional: ruby-gtk2: For status icon while backupping
|
55
|
+
* optional: syslog-ng: For syslog functionality
|
56
|
+
|
57
|
+
|
58
|
+
== INSTALL:
|
59
|
+
|
60
|
+
* sudo gem install
|
61
|
+
|
62
|
+
== DEVELOPERS:
|
63
|
+
|
64
|
+
After checking out the source, run:
|
65
|
+
|
66
|
+
$ rake newb
|
67
|
+
|
68
|
+
This task will install any missing dependencies, run the tests/specs,
|
69
|
+
and generate the RDoc.
|
70
|
+
|
71
|
+
== LICENSE:
|
72
|
+
|
73
|
+
(GPL)
|
74
|
+
|
75
|
+
Copyright (c) 2009 Jan Rüegg <rggjan@gmail.com>
|
76
|
+
|
77
|
+
Smarbs is free software; you can redistribute it and/or modify it
|
78
|
+
under the terms of the GNU General Public License as published by
|
79
|
+
the Free Software Foundation; either version 3 of the License, or
|
80
|
+
(at your option) any later version.
|
81
|
+
|
82
|
+
This program is distributed in the hope that it will be useful,
|
83
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
84
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
85
|
+
General Public License for more details.
|
86
|
+
|
87
|
+
You can find a copy of the GNU General Public License under
|
88
|
+
http://www.gnu.org/licenses/
|
data/Rakefile
ADDED
data/bin/smarbs
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'script'
|
3
|
+
require 'types'
|
4
|
+
|
5
|
+
$stdout.sync = true # rsync "realtime" output
|
6
|
+
|
7
|
+
if Directory.writable?("/etc/smarbs")
|
8
|
+
script=Script.new("/etc/smarbs", ARGV)
|
9
|
+
else
|
10
|
+
script=Script.new(File.expand_path("~/.smarbs"), ARGV)
|
11
|
+
end
|
data/lib/backup.rb
ADDED
@@ -0,0 +1,275 @@
|
|
1
|
+
require 'log'
|
2
|
+
require 'helpers'
|
3
|
+
require 'types'
|
4
|
+
|
5
|
+
# A class that has individual backups as instances.
|
6
|
+
class Backup
|
7
|
+
|
8
|
+
# Initializes the a backup, takes as arguments a Configfile, some
|
9
|
+
# rsync_arguments and the information if it should be verbose.
|
10
|
+
def initialize(path, rsync_arguments, verbose)
|
11
|
+
@rsync_arguments = rsync_arguments
|
12
|
+
@verbose = verbose
|
13
|
+
@logger = nil
|
14
|
+
@configfile = nil
|
15
|
+
|
16
|
+
begin
|
17
|
+
@configfile = ConfigFile.new(path)
|
18
|
+
|
19
|
+
logfile = @configfile.logfile
|
20
|
+
if logfile == ""
|
21
|
+
if @configfile.logdir == ""
|
22
|
+
logfile = "/tmp/" + Time.now.strftime("%Y-%m-%d.%Hh%M")
|
23
|
+
else
|
24
|
+
logfile = @configfile.logdir + "/" + Time.now.strftime("%Y-%m-%d.%Hh%M")+"-"+@configfile.filename.to_s+".log"
|
25
|
+
end
|
26
|
+
else
|
27
|
+
logfile = @configfile.logfile
|
28
|
+
end
|
29
|
+
|
30
|
+
@logger = Log.new(logfile, @configfile.advancedlog, @configfile.syslog)
|
31
|
+
|
32
|
+
@configfile.write
|
33
|
+
|
34
|
+
@logger.p("-" * 20, 98)
|
35
|
+
@logger.p("Working on " + @configfile.filename, 2)
|
36
|
+
@logger.p("-" * 20, 98)
|
37
|
+
@logger.p("\nChecking configfile...")
|
38
|
+
|
39
|
+
if @configfile.sendmail
|
40
|
+
@logger.initialize_email(@configfile.email, @configfile.smtp,
|
41
|
+
@configfile.port, @configfile.uname, @configfile.passwd,
|
42
|
+
@configfile.tls, @configfile.testm, path.split("/")[-1])
|
43
|
+
if @configfile.testm
|
44
|
+
@logger.p("The test e-mail has been successfully sent to " + @configfile.email + ",", 2, 1)
|
45
|
+
@configfile.testm=false
|
46
|
+
@configfile.write
|
47
|
+
@logger.p("testm has been automatically set to 'no'.", 2, 1)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
raise "No 'rsync' installed!" unless command_exists?("rsync")
|
52
|
+
raise "No 'du' installed!" unless command_exists?("du")
|
53
|
+
raise "No 'df' installed!" unless command_exists?("df")
|
54
|
+
readcf
|
55
|
+
|
56
|
+
if not @configfile.execute_before.empty? then
|
57
|
+
output = `#{@configfile.execute_before} 2>&1`
|
58
|
+
raise "execute_before command '" + @configfile.execute_before + "' was not successful, aborting!\nThis was the output generated:\n" + output unless $?.exitstatus == 0
|
59
|
+
end
|
60
|
+
|
61
|
+
@backup_dir = SmarbsBackupDir.new(@configfile.dest + "/" + "smarbsbackup", @configfile.ignore_leftovers)
|
62
|
+
|
63
|
+
backup
|
64
|
+
|
65
|
+
if not @configfile.execute_after.empty? then
|
66
|
+
output = `#{@configfile.execute_after} 2>&1`
|
67
|
+
raise(AfterException, "execute_after command '" + @configfile.execute_after + "' was not successful, aborting!\nThis was the output generated:\n" + output) unless $?.exitstatus == 0
|
68
|
+
end
|
69
|
+
|
70
|
+
rescue AfterException
|
71
|
+
message = $!.to_s + "\nCheck your configfile " + path + "."
|
72
|
+
if @logger.nil?
|
73
|
+
puts "Error: " + message
|
74
|
+
else
|
75
|
+
@logger.p(message, 4)
|
76
|
+
end
|
77
|
+
rescue NoConfigException
|
78
|
+
@configfile.execute_after = "" if @configfile.execute_after.nil?
|
79
|
+
message = $!.to_s
|
80
|
+
if not @configfile.execute_after.empty? then
|
81
|
+
output = `#{@configfile.execute_after} 2>&1`
|
82
|
+
if $?.exitstatus != 0 then
|
83
|
+
message = "execute_after command '" + @configfile.execute_after + "' was not successful, aborting!\nThis was the output generated:\n" + output + "\nAlso, your backup was aborted: " + message
|
84
|
+
end
|
85
|
+
end
|
86
|
+
if @logger.nil?
|
87
|
+
puts "Error: " + message
|
88
|
+
else
|
89
|
+
@logger.p(message, 4)
|
90
|
+
end
|
91
|
+
rescue
|
92
|
+
message = $!.to_s + "\nCheck your configfile " + path + "."
|
93
|
+
@configfile.execute_after = "" if @configfile.execute_after.nil? unless @configfile.nil?
|
94
|
+
if not @configfile.execute_after.empty? then
|
95
|
+
output = `#{@configfile.execute_after} 2>&1`
|
96
|
+
if $?.exitstatus != 0 then
|
97
|
+
message = "execute_after command '" + @configfile.execute_after + "' was not successful, aborting!\nThis was the output generated:\n" + output + "\nAlso, your backup was aborted: " + message
|
98
|
+
end
|
99
|
+
end unless @configfile.nil?
|
100
|
+
if @logger.nil?
|
101
|
+
puts "Error: " + message
|
102
|
+
else
|
103
|
+
@logger.p(message, 4)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def command_exists?(command)
|
111
|
+
`#{command} --version 2>/dev/null`
|
112
|
+
return $?.exitstatus == 0
|
113
|
+
end
|
114
|
+
|
115
|
+
def readcf
|
116
|
+
raise "No source directory specified!" unless @configfile.src != [""]
|
117
|
+
@configfile.src.each do |dir|
|
118
|
+
raise "Source directory/file " + dir + " not existing!" unless File.directory?(dir) or File.file?(dir)
|
119
|
+
end
|
120
|
+
raise "No destination directory specified!" unless @configfile.dest != ""
|
121
|
+
|
122
|
+
@options = ""
|
123
|
+
@options += " --exclude='" + @configfile.exclude.join("' --exclude='") + "'" unless @configfile.exclude[-1] == ""
|
124
|
+
@options += " -rltD"
|
125
|
+
|
126
|
+
|
127
|
+
@options += "og" if @configfile.preserveowner
|
128
|
+
@options += "p" if @configfile.preservepermissions
|
129
|
+
@options += "v --progress " if @verbose or @configfile.verbose
|
130
|
+
@options += " -x " if @configfile.onefilesystem
|
131
|
+
@options += " --relative " if @configfile.relative
|
132
|
+
@options += " --modify-window=#{@configfile.modifywindow}" if @configfile.modifywindow != 0
|
133
|
+
end
|
134
|
+
|
135
|
+
def make_space(used, avail, text_only=false)
|
136
|
+
@logger.p("", 2)
|
137
|
+
@logger.p("estimated new space used: " + Size.new(used).opt, 2)
|
138
|
+
@logger.p("available space: " + Size.new(avail).opt, 2)
|
139
|
+
@backup_dir.delete(@logger, @configfile.minbackuplevels, @configfile.oldestfirst) unless text_only
|
140
|
+
end
|
141
|
+
|
142
|
+
def delete(to_free)
|
143
|
+
while (@backup_dir.dirlist.size >= @configfile.maxbackuplevels) do
|
144
|
+
@logger.p("", 98)
|
145
|
+
@logger.p("maxbackuplevels: " + @configfile.maxbackuplevels.to_s, 1)
|
146
|
+
@logger.p("backups: " + @backup_dir.dirlist.size.to_s, 1)
|
147
|
+
@backup_dir.delete(@logger, @configfile.minbackuplevels, @configfile.oldestfirst)
|
148
|
+
end unless @configfile.maxbackuplevels == 0
|
149
|
+
|
150
|
+
if @configfile.ownpartition then
|
151
|
+
now_free=@backup_dir.free
|
152
|
+
while to_free > now_free do
|
153
|
+
make_space(to_free, now_free)
|
154
|
+
now_free=@backup_dir.free
|
155
|
+
end
|
156
|
+
make_space(to_free, now_free, true)
|
157
|
+
cursize = @backup_dir.space(true)
|
158
|
+
elsif @configfile.exclusive then
|
159
|
+
cursize=@backup_dir.space
|
160
|
+
while cursize + to_free > @configfile.limit.b do
|
161
|
+
before = @backup_dir.free
|
162
|
+
make_space(to_free, @configfile.limit.b-cursize)
|
163
|
+
after = @backup_dir.free
|
164
|
+
cursize -= (after - before)
|
165
|
+
end
|
166
|
+
make_space(to_free, @configfile.limit.b-cursize, true)
|
167
|
+
else
|
168
|
+
cursize=@backup_dir.space
|
169
|
+
while cursize + to_free > @configfile.limit.b do
|
170
|
+
make_space(to_free, @configfile.limit.b-cursize)
|
171
|
+
cursize=@backup_dir.space
|
172
|
+
end
|
173
|
+
make_space(to_free, @configfile.limit.b-cursize, true)
|
174
|
+
end
|
175
|
+
@logger.p("", 98)
|
176
|
+
return cursize
|
177
|
+
end
|
178
|
+
|
179
|
+
def backup
|
180
|
+
|
181
|
+
dest = @backup_dir.to_s + Time.now.strftime("%Y-%m-%d.%Hh%M") + "-backup.0"
|
182
|
+
|
183
|
+
if @configfile.ignore_leftovers
|
184
|
+
directory_left = @backup_dir.directory_left
|
185
|
+
if directory_left
|
186
|
+
@logger.p("Warning: Aborted backup directory #{directory_left} detected.
|
187
|
+
Resuming backup there because of ignore_leftovers option.", 3)
|
188
|
+
|
189
|
+
orig_dest = dest
|
190
|
+
dest = @backup_dir.to_s + directory_left
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
if @backup_dir.dirlist.size!=0
|
195
|
+
if orig_dest
|
196
|
+
linkdest=@backup_dir.to_s+(@backup_dir.dirlist[1][1]).to_s+"-backup."+(@backup_dir.dirlist[1][0]).to_s
|
197
|
+
else
|
198
|
+
linkdest=@backup_dir.to_s+(@backup_dir.dirlist[0][1]).to_s+"-backup."+(@backup_dir.dirlist[0][0]).to_s
|
199
|
+
end
|
200
|
+
@rsync_arguments += " --link-dest='" + linkdest + "' "
|
201
|
+
end
|
202
|
+
|
203
|
+
@logger.p("\nCalculating required space...", 1)
|
204
|
+
|
205
|
+
required = `rsync #@options #@rsync_arguments -n --stats --delete '#{@configfile.src.join"' '"}' '#{dest}/' 2>/dev/null | tail -n 11 | (read a b c d e f; echo $e)`.to_f
|
206
|
+
|
207
|
+
@logger.p("\nDeleting old backups...", 1)
|
208
|
+
|
209
|
+
begin
|
210
|
+
size_before=delete(required + @configfile.dirspace.b * 1.5)
|
211
|
+
|
212
|
+
@logger.p("Backing up...\n\n", 2)
|
213
|
+
|
214
|
+
system("rsync #@options #@rsync_arguments --delete '#{@configfile.src.join"' '"}' '#{dest}/'")
|
215
|
+
|
216
|
+
success=$?.exitstatus
|
217
|
+
|
218
|
+
case success
|
219
|
+
when 0
|
220
|
+
@logger.p("", 98) if @verbose
|
221
|
+
@logger.p("Successfully backed up.\n\n", 2, 1)
|
222
|
+
@logger.p("Successfully backed up.", 99, 1) if @configfile.successmail
|
223
|
+
when 1
|
224
|
+
raise NoConfigException, "Your --pass-rsync argument '" + @rsync_arguments.to_s + "' is invalid!"
|
225
|
+
when 24
|
226
|
+
@logger.p("Warning: Some files couldn't be transferred because they vanished!", 3)
|
227
|
+
@logger.p("Successfully backed up.\n\n", 2, 1)
|
228
|
+
@logger.p("Successfully backed up.\n\n", 99, 1) if @configfile.successmail
|
229
|
+
when nil
|
230
|
+
raise NoConfigException, "rsync was stopped unexpectedly!"
|
231
|
+
else
|
232
|
+
raise NoConfigException, "rsync failed with error code #{success}."
|
233
|
+
end
|
234
|
+
|
235
|
+
FileUtils.mv dest, orig_dest if orig_dest
|
236
|
+
|
237
|
+
@backup_dir.increment
|
238
|
+
|
239
|
+
size_after = @backup_dir.space(@configfile.ownpartition)
|
240
|
+
newdirspace=size_after - size_before - required
|
241
|
+
newdirspace = newdirspace*1.1 # Safety margin
|
242
|
+
newdirspace = Size.new(newdirspace)
|
243
|
+
if @backup_dir.dirlist.size > 1
|
244
|
+
if newdirspace.b > @configfile.dirspace.b
|
245
|
+
@configfile.dirspace = newdirspace.b
|
246
|
+
@configfile.write
|
247
|
+
else
|
248
|
+
if newdirspace.b >= 0
|
249
|
+
@configfile.dirspace = @configfile.dirspace.b*0.9 + newdirspace.b*0.1
|
250
|
+
else
|
251
|
+
@configfile.dirspace = @configfile.dirspace.b*0.9
|
252
|
+
end
|
253
|
+
@configfile.write
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
size_one = `du -bcs #{@backup_dir.to_s}*backup.1 | tail -1 | (read a b; echo $a)`.strip
|
258
|
+
|
259
|
+
@logger.p("Additional Space used: #{Size.new(size_after - size_before).opt}", 1)
|
260
|
+
@logger.p("Size of all the Backups: #{Size.new(size_after).opt}", 1)
|
261
|
+
@logger.p("Size of one full Backup: #{Size.new(size_one).opt}\n\n", 1)
|
262
|
+
if @configfile.ownpartition then
|
263
|
+
@logger.p("Limit: ignored (ownpartition is set)", 1)
|
264
|
+
else
|
265
|
+
@logger.p("Limit: " + @configfile.limit.opt, 1)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
class AfterException < RuntimeError
|
272
|
+
end
|
273
|
+
|
274
|
+
class NoConfigException < RuntimeError
|
275
|
+
end
|
@@ -0,0 +1,209 @@
|
|
1
|
+
=preferences=
|
2
|
+
|
3
|
+
src: Directory(list)
|
4
|
+
-- One or more directories to the source (= directory or file you need a backup
|
5
|
+
-- backup from. One directory / file per line only.
|
6
|
+
src /directory/to/source1
|
7
|
+
src /directory/to/source2
|
8
|
+
|
9
|
+
dest: Directory
|
10
|
+
-- One (!) destination directory:
|
11
|
+
dest /directory/to/the/destination
|
12
|
+
|
13
|
+
limit: Size
|
14
|
+
-- Limit of space to use for the full and all the incremental backups:
|
15
|
+
-- (ignored when using "ownpartition", see below)
|
16
|
+
limit 20m
|
17
|
+
|
18
|
+
minbackuplevels: Integer(positive)
|
19
|
+
-- Minimum number of backups to keep.
|
20
|
+
-- Smarbs will throw an error if there is not enough space available to backup,
|
21
|
+
-- or the next deletion would go below "minbackuplevels".
|
22
|
+
minbackuplevels 5
|
23
|
+
|
24
|
+
verbose: Boolean
|
25
|
+
-- More output when a yes is here:
|
26
|
+
verbose no
|
27
|
+
|
28
|
+
=filesystems=
|
29
|
+
|
30
|
+
ownpartition: Boolean
|
31
|
+
-- If there is an entire partition just for the backups, then here should be a
|
32
|
+
-- yes. Uses the whole partition for this backup, the limit set above is
|
33
|
+
-- ignored. This is MUCH faster than the normal space calculations, but
|
34
|
+
-- requires an own partition for every backup.
|
35
|
+
ownpartition no
|
36
|
+
|
37
|
+
exclusive: Boolean
|
38
|
+
-- Does deletion using 'df' instead of 'du', what increases speed (much).
|
39
|
+
-- Can ONLY be used, if NO other processes write to the destination partition
|
40
|
+
-- during the backup. Has only an effect when 'ownpartition' is false.
|
41
|
+
exclusive no
|
42
|
+
|
43
|
+
onefilesystem: Boolean
|
44
|
+
-- Don't cross filesystem boundaries. This tells smarbs to avoid crossing a
|
45
|
+
-- filesystem boundary when recursing. This does not limit the user's
|
46
|
+
-- ability to specify items to copy from multiple filesystems.
|
47
|
+
onefilesystem no
|
48
|
+
|
49
|
+
preserveowner: Boolean
|
50
|
+
-- Preserve the owner / group of files:
|
51
|
+
-- Owner preserving does NOT work if the script is not executed as superuser.
|
52
|
+
preserveowner yes
|
53
|
+
|
54
|
+
preservepermissions: Boolean
|
55
|
+
-- Preserve the permissions of files:
|
56
|
+
preservepermissions yes
|
57
|
+
|
58
|
+
modifywindow: Integer
|
59
|
+
-- When comparing two timestamps, smarbs treats the timestamps as being equal
|
60
|
+
-- if they differ by no more than the modifywindow value. This is normally
|
61
|
+
-- 0 (for an exact match), but you may find it useful to set this to a larger
|
62
|
+
-- value in some situations. In particular, when transferring to or from an
|
63
|
+
-- Windows FAT filesystem (which represents times with a 2-second resolution),
|
64
|
+
-- modifywindow 1 is useful (allowing times to differ by up to 1 second).
|
65
|
+
modifywindow 0
|
66
|
+
|
67
|
+
maxbackuplevels: Integer(positive)
|
68
|
+
-- Maximum number of backups to keep.
|
69
|
+
-- Smarbs will delete backups if there are more incremental backups than given
|
70
|
+
-- here. This may be useful if space calculations take too much time (due to
|
71
|
+
-- more and more incremental backups and hardlinks).
|
72
|
+
-- 0 means infinity and is recommended, if the speed is acceptable.
|
73
|
+
maxbackuplevels 0
|
74
|
+
|
75
|
+
dirspace: Size
|
76
|
+
-- How much space is used by hardlinks and directories? Used to do space
|
77
|
+
-- calculations. Should be adapted automatically by smarbs, so you shouldn't
|
78
|
+
-- have to touch that...
|
79
|
+
dirspace 1m
|
80
|
+
|
81
|
+
=advanced=
|
82
|
+
|
83
|
+
execute_before: String
|
84
|
+
-- A command to execute (in a shell) before the backup is done.
|
85
|
+
-- Example:
|
86
|
+
-- execute_before mount /directory/to/source1
|
87
|
+
execute_before
|
88
|
+
|
89
|
+
execute_after: String
|
90
|
+
-- A command to execute (in a shell) after the backup , regardless if it was
|
91
|
+
-- successful or not.
|
92
|
+
-- Example:
|
93
|
+
-- execute_after umount /directory/to/source1
|
94
|
+
execute_after
|
95
|
+
|
96
|
+
relative: Boolean
|
97
|
+
-- Use relative paths. This means that the full path names of the sources are
|
98
|
+
-- sent to the backup folder rather than just the last parts of the filenames.
|
99
|
+
-- This is particularly useful when you want to backup several different
|
100
|
+
-- directories with the same name, or to preserve a whole directory structure.
|
101
|
+
-- So you get .../smarbsbackup/2008-03-01.11h10-backup.1/directory/to/source1
|
102
|
+
-- instead of just .../smarbsbackup/2008-03-01.11h10-backup.1/source1
|
103
|
+
relative no
|
104
|
+
|
105
|
+
oldestfirst: Boolean
|
106
|
+
-- Delete the oldest backups first when no more space is available, instead of
|
107
|
+
-- using the established "powers of two" algorithm, that keeps the backups 1,
|
108
|
+
-- 2, 4, 8, 16, 32 etc. Recommended to set to 'no'!
|
109
|
+
-- See https://sourceforge.net/apps/trac/smarbs/wiki/DeletionAlgorithm for more
|
110
|
+
-- informations.
|
111
|
+
oldestfirst no
|
112
|
+
|
113
|
+
exclude: String(list)
|
114
|
+
-- Directories / files to exclude. Path relative to the "root of transfer" when
|
115
|
+
-- starting with a "/". So "exclude /source1/foo" excludes files or directories
|
116
|
+
-- named foo in /directory/to/source1 while "exclude foo" excludes EVERY
|
117
|
+
-- directory or file named foo in source1 or source2. "exclude sub/foo" would
|
118
|
+
-- exclude EVERY file or directory named foo which is in a folder "sub".
|
119
|
+
-- Syntax: One line per exclude.
|
120
|
+
-- Example:
|
121
|
+
-- exclude *.jpg
|
122
|
+
-- exclude /sub/*/foo
|
123
|
+
exclude
|
124
|
+
|
125
|
+
ignore_leftovers: Boolean
|
126
|
+
-- Normally, when an aborted backup directory (...backup.0 instead of 1) is
|
127
|
+
-- detected, smarbs treats this as an error, stops and does not do a backup at
|
128
|
+
-- at all. When ignore_leftovers is set to "yes", it just prints a warning and
|
129
|
+
-- continues the last backup.
|
130
|
+
ignore_leftovers: no
|
131
|
+
|
132
|
+
=logging=
|
133
|
+
|
134
|
+
logfile: Directory
|
135
|
+
-- Place of the (error) log file:
|
136
|
+
-- Example:
|
137
|
+
-- logfile /home/me/smarbslog.log
|
138
|
+
logfile
|
139
|
+
|
140
|
+
logdir: Directory
|
141
|
+
-- Place of a possible log directory. Has no effect when a logfile is set.
|
142
|
+
-- Otherwise, instead of writing logs into one file, logfiles are stored in the
|
143
|
+
-- directory below like this for each backup:
|
144
|
+
-- /.../logdir/2009-02-06.20h09-backup1.log
|
145
|
+
-- If logfile and logdir are not set, the logdir will be /tmp/
|
146
|
+
-- Example:
|
147
|
+
-- logdir /home/me/smarbslogs/
|
148
|
+
logdir
|
149
|
+
|
150
|
+
advancedlog: Boolean
|
151
|
+
-- Do advanced logging (show deletions, space informations etc. instead of just
|
152
|
+
-- success and failure messages).
|
153
|
+
advancedlog yes
|
154
|
+
|
155
|
+
syslog: Boolean
|
156
|
+
-- Log to syslog instead of build-in logger, above options will be ignored.
|
157
|
+
-- You will have to configure your syslog daemon accordingly, check README for
|
158
|
+
-- examples.
|
159
|
+
-- DO NOT enable unless you know what you are doing, and have root access
|
160
|
+
syslog no
|
161
|
+
|
162
|
+
=email notification=
|
163
|
+
|
164
|
+
sendmail: Boolean
|
165
|
+
-- Send an email in case of an error, the logfile will be attached.
|
166
|
+
sendmail no
|
167
|
+
|
168
|
+
successmail: Boolean
|
169
|
+
-- Send also an email for successful backups:
|
170
|
+
successmail no
|
171
|
+
|
172
|
+
email: String
|
173
|
+
-- Email address to send it to.
|
174
|
+
-- Example:
|
175
|
+
-- email rggjan@gmail.com
|
176
|
+
email
|
177
|
+
|
178
|
+
smtp: String
|
179
|
+
-- Smtp server.
|
180
|
+
-- Example:
|
181
|
+
-- smtp smtp-auth.freesurf.ch
|
182
|
+
smtp
|
183
|
+
|
184
|
+
port: Integer
|
185
|
+
-- Port to use:
|
186
|
+
port 25
|
187
|
+
|
188
|
+
uname: String
|
189
|
+
-- When authentication is required, put here the username.
|
190
|
+
-- Example:
|
191
|
+
-- uname rggjan@gmail.com
|
192
|
+
uname
|
193
|
+
|
194
|
+
passwd: String
|
195
|
+
-- When authentication is required, put here the username.
|
196
|
+
-- Example:
|
197
|
+
-- passwd topsecret
|
198
|
+
passwd
|
199
|
+
|
200
|
+
tls: Boolean
|
201
|
+
-- Use tls (ssl). That's required for some smtp servers like Gmail.
|
202
|
+
-- You need to have ruby-openssl installed to use this!
|
203
|
+
tls no
|
204
|
+
|
205
|
+
testm: Boolean
|
206
|
+
-- Send a test email to see if your smtp options are ok. This should
|
207
|
+
-- definitely be a "yes" at the beginning to check if the connection works.
|
208
|
+
-- Will be automatically set to "no" once the email is successfully sent.
|
209
|
+
testm yes
|
Binary file
|
Binary file
|
Binary file
|
data/lib/data/intro.txt
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
Smarbs space-managing-rsync-backup-script
|
2
|
+
rsync and ruby are required!
|
3
|
+
|
4
|
+
For each different backup you should create a file like this in the directory
|
5
|
+
/home/"user"/.smarbs/ (or /etc/smarbs/ if you are root).
|
6
|
+
|
7
|
+
You can start a backup using "smarbs backup1" or "smarbs homebackup" assuming
|
8
|
+
there is a file named "backup1" or "homebackup" in the smarbs folder.
|
9
|
+
A simple "smarbs" or a "smarbs all" will do a backup with all the different
|
10
|
+
configurations in the smarbs directory.
|
11
|
+
|
12
|
+
Sizes: 2394 Bytes (B) => 2394
|
13
|
+
32 Kibibytes (MiB) => 32k
|
14
|
+
54 Mebibytes (MiB) => 54m
|
15
|
+
2 Gibibytes (KiB) => 2g
|
16
|
+
|
data/lib/data/outro.txt
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
-------------------------------end of preferences-------------------------------
|
2
|
+
|
3
|
+
This program is free software: you can redistribute it and/or modify
|
4
|
+
it under the terms of the GNU General Public License as published by
|
5
|
+
the Free Software Foundation, either version 3 of the License, or
|
6
|
+
(at your option) any later version.
|
7
|
+
|
8
|
+
This program is distributed in the hope that it will be useful,
|
9
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
GNU General Public License for more details.
|
12
|
+
|
13
|
+
See <http://www.gnu.org/licenses/> for a copy of the GNU General Public License.
|
14
|
+
|
15
|
+
For any suggestions, comments or bug reports, write to rggjan@gmail.com
|