backupgem 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,6 @@
1
+ = Backup Changelog
2
+
3
+ == Version 0.0.2
4
+
5
+ * First stable code in place.
6
+ * Packaged in an gem format
data/README ADDED
@@ -0,0 +1,387 @@
1
+ ===What is Backup?===
2
+ <tt>Backup</tt> is the easiest and most flexible backup, archive and rotate
3
+ tool. It's a beginning-to-end solution for scheduled backups in a clean ruby
4
+ package that is simple use and powerful when customized.
5
+
6
+ Backup allows you to specify each of the following options:
7
+ * what is being archived (files, folders, arbitrary scripts)
8
+ * how it's being archived (tar gzip, bz2)
9
+ * where the archive is going (multiple backup servers? easy)
10
+ * how the archive is going to get there (scp, ftp, mv)
11
+ * where is will be stored when it gets there
12
+ * how it's going to be rotated when it gets there (grandfather-father-son, etc)
13
+ * how often will this process happen (customizable cycles)
14
+ * what happens to the working copy after the process (recreate files, folders etc. restart daemons)
15
+
16
+ Backup is a collection of scripts that is complete enough to save you
17
+ time, but flexible enough to work with any situation.
18
+
19
+ ===Getting Backup===
20
+ ====Prerequisites====
21
+ Backup makes the following assumptions about your machines:
22
+ * server and client understand POSIX commmands
23
+ * passwords and paths are the same on each server
24
+
25
+ Backup depends on the following libraries:
26
+ * [[Runt]] for describing [[temporal ranges]]
27
+ * [[Net::SSH]] for SSH backups
28
+ * [[Net::FTP]] for FTP backups
29
+
30
+ These are listed as dependencies in the gem file so you should be prompted to
31
+ install them when you install Backup.
32
+
33
+ ====Using RubyGems====
34
+ If you have [[http://rubygems.rubyforge.org RubyGems]] installed, installing
35
+ Backup is simple:
36
+
37
+ sudo gem install backupgem
38
+
39
+ ====Using svn====
40
+ If you prefer, you can checkout backupgem from the [[RubyForge Repository]].
41
+ Feel free to browse the releases or trunk [[here]].
42
+
43
+ svn+ssh://blar blar blar
44
+
45
+ ===License Information===
46
+ Backup is made available under either the BSD license, or the same license Ruby
47
+ (which, by extension, also allows the GPL as a permissable license as well).
48
+ You can view the full text of any of these licenses in the <tt>doc</tt> subdirectory
49
+ of the Backup distrubtion. The texts of the BSD and GPL licenses are also
50
+ available online: "BSD":http://www.opensource.org/licenses/bsd-license.php and
51
+ "GPL":http://www.opensource.org/licenses/gpl-license.php.
52
+
53
+ If you desire permission to use either Backup in a manner incompatible with
54
+ these licenses, please contact the copyright holder
55
+ ([[mailto:nate@natemurray.com Nate Murray]] in order to negotiate a more
56
+ compatible license.
57
+
58
+ ===Support===
59
+ Mailing lists, bug trackers, feature requests, and public forums are all
60
+ available courtesty of [[http://rubyforge.org RubyForge]] at the
61
+ [[http://rubyforge.org/projects/backupgem BackupGem project page]].
62
+
63
+ ====Mailing Lists====
64
+ {|class="wikitable"
65
+ ! List Name
66
+ !
67
+ ! Desc.
68
+ |---
69
+ | [[http://rubyforge.org/pipermail/backupgem-users backupgem-users]]
70
+ | [[http://rubyforge.org/mailman/listinfo/backupgem-users subscribe / unsubscribe]]
71
+ | The BackupGem users list is devoted to the discussion of and questions about the usage of Backup. If you can't quite figure out how to get a feature of Backup to work, this is the list you would go to in order to ask your questions.
72
+ |---
73
+ | [[http://rubyforge.org/pipermail/backupgem-devel backupgem-devel]]
74
+ | [[http://rubyforge.org/mailman/listinfo/backupgem-devel subscribe / unsubscribe]]
75
+ | The Backup developers list is devoted to the discussion of Backup's implementation. If you have created a patch that you would like to discuss, or if you would like to discuss a new feature, this is the list for you.
76
+ |}
77
+
78
+ ===About the Author===
79
+ Backup was written by [[mailto:nate@natemurray.com Nate Murray].
80
+ Nate currently works at an internet retailer in Southern California.
81
+ Feel free to send him compliments, candy, money, praise, or new feature patches--he likes
82
+ all those things. You can send him questions and suggestions, too, if you
83
+ really want to. However, for bug reports and general feature requests,
84
+ please use the trackers on the [[http://rubyforge.org/projects/backupgem BackupGem project page]].
85
+
86
+ ===Special Thanks===
87
+ * Matt Pulver for help with various technical problems and ideas.
88
+
89
+ * Jamis Buck for writing [http://weblog.rubyonrails.com/2006/8/30/capistrano-1-1-9-beta Capistrano]. Capistrano provided the inspiration and some code for this work. Additionally, the Net::SSH manual provided the inspiration for this manual. Thanks for the top-notch work Jamis!
90
+
91
+ * [[mailto:info@digitalclash.com Matthew Lipper]] for writing the Runt Ruby Temporal Expressions Library
92
+
93
+ ==How Backup Works==
94
+ ===Intro===
95
+ A basic backup has the following sequence:
96
+ * content
97
+ * compress
98
+ * encrypt
99
+ * deliver
100
+ * rotate
101
+ * cleanup
102
+
103
+ This order is the default, however, like most things it is customizable.
104
+ Think of it like a pipline: the input of each step is the output of the last
105
+ step.
106
+
107
+ Each of these things are specified in a <tt>recipe</tt> file which is describe below.
108
+
109
+ ===CLI===
110
+
111
+ Usage: ./backup [options]
112
+ Recipe Options -----------------------
113
+ -r, --recipe RECIPE A recipe file to load. Multiple recipes
114
+ may be specified, and are loaded in the
115
+ given order.
116
+ -g, --global FILE Specify the global recipe file to work
117
+ with. Defaults to the file <tt>global.rb</tt>
118
+ in the directory of <tt>recipe</tt>
119
+ -s, --set NAME=VALUE Specify a variable and it's value to
120
+ set. This will be set after loading all
121
+ recipe files.
122
+
123
+ ==Backup Recipe File Format==
124
+ ===Introduction===
125
+ * The Backup Recipe format is pure ruby code. Anything that is valid ruby is valid in the recipe file. There are a number of shortcuts that will make your life easier.
126
+
127
+ * Each of the steps are specified as an <tt>action</tt>. (An action is really nothing more than a method that becomes defined in the Actor instance. See API docs if you're interestd.)
128
+
129
+ * You may create "hook" actions for any of the actions. So if you define a method <tt>before_content</tt> it will be called just before <tt>content</tt> is called. A method named <tt>after_rotation</tt> would be called after rotation. This may not always be needed as you can customize the rotation order to be whatever you want. See [[#XXX]] below.
130
+
131
+ * Each action has the variable <tt>last_result</tt> available to it. This is the return value of the method that was called previously. Note that this includes the output of the "hook" methods.
132
+
133
+ * All configuration variables are available to actions via the hash c[]. For example, the backup path is available to your actions as c[:backup_path].
134
+
135
+ ===Variables===
136
+ Intro on how to set variables. How this works.
137
+
138
+ Required variables for all configurations.
139
+ {|class="wikitable"
140
+ ! Name
141
+ ! Desc.
142
+ ! Example
143
+ |---
144
+ | :action_order
145
+ | short desc. TODO
146
+ | set :action_order, %w{ content compress encrypt deliver rotate cleanup }
147
+ |---
148
+ | :tmp_dir
149
+ | Specify a directory that backup can use as a temporary directory. Default <tt>/tmp</tt>.
150
+ | set :tmp_dir, File.dirname(__FILE__) + "/../tmp"
151
+ |---
152
+ | :backup_path
153
+ | The path to backup on. TODO - if its local the local server if its foreign the foreign server
154
+ | set :backup_path, "/var/local/backups/mediawiki"
155
+ |}
156
+
157
+ ===Content===
158
+ The first step in any backup is the content that is to be backed up. Backup
159
+ provides a couple of shortcuts for common ways to locate content and allows you
160
+ to arbitrarily define your own.
161
+
162
+ Some typical types of content are:
163
+ * a particular file
164
+ * a particular folder
165
+ * the contents of a particular folder
166
+
167
+ These could be specified like so:
168
+
169
+ action :content, :is_file => "/path/to/file" # content is a single file
170
+ action :content, :is_file => "/path/to/error_log", :recreate => true
171
+ action :content, :is_folder => "/path/to/folder" # content is the folder itself
172
+ action :content, :is_contents_of => "/path/to/other/folder" # content is folder/* , recursive option
173
+
174
+ If you want :content to be a series of shell commands just pass "action" a block:
175
+
176
+ action(:content) do
177
+ sh "echo \"hello $HOSTNAME\""
178
+ sh "mysqldump -uroot database > /path/to/db.sql"
179
+ "/path/to/db.sql" # make sure you return the full path to the folder/file you wish to be the content
180
+ end
181
+
182
+ ===Compress===
183
+ Next you may want to compress your content. Again, there are a few one-liners for common cases and you can create your own.
184
+
185
+ action :compress, :method => :tar_bz2 # actually calls a method named tar_bz2 with output of ":content" ( or ":after_content" )
186
+ # or
187
+ action :compress, :method => :tar_gzip
188
+
189
+ Again, you can create your own.
190
+
191
+ action(:compress)
192
+ sh "my_tar #{last_result} #{last_result}.tar"
193
+ sh "my_bzip #{last_result}.tar #{last_result}.tar.bz2"
194
+ last_result + ".tar.bz2"
195
+ end
196
+
197
+ ===Encrypt===
198
+ If you wish to use encryption this is available to you. I would recommend that
199
+ you think seriously about how you wish to manage your keys for this backup
200
+ process. If you are backing up encrypted data then you need to backup your keys
201
+ or else you risk losing access to your data. Secure key management is beyond
202
+ the scope of this document, but I recommend the following links:
203
+ * link 1
204
+ * link 2
205
+
206
+ set :encrypt, true # default is <tt>false</tt>
207
+ set :gpg_encrypt_options, "--default-recipient" # default is an empty string
208
+ action :encrypt, :method => :gpg # default, none
209
+
210
+ or your own:
211
+
212
+ action(:encrypt)
213
+ sh "gpg #{c[:gpg_encrypt_options]} --encrypt #{last_result}"
214
+ last_result + ".gpg" # ?
215
+ end
216
+
217
+ ===Delivery===
218
+ ====Action====
219
+ Delivery is supported via <tt>scp</tt>, <tt>ftp</tt>, and <tt>mv</tt>
220
+
221
+ action :delivery, :method => :scp
222
+ action :delivery, :method => :ftp
223
+ action :delivery, :method => :mv
224
+
225
+ The <tt>:mv</tt> action is defined like any user-defined action:
226
+
227
+ action(:mv) do
228
+ sh "mv #{last_result} #{c[:backup_path]}/"
229
+ c[:backup_path] <tt> "/" </tt> File.basename(last_result)
230
+ end
231
+
232
+ ====Variables====
233
+ {|class="wikitable"
234
+ ! Name
235
+ ! Desc.
236
+ ! Example
237
+ |---
238
+ | :servers
239
+ | An array of host names to deliver the data to. TODO this currently only supports 1 server.
240
+ | set :servers, %w{ localhost }
241
+ |---
242
+ | :ssh_user
243
+ | The name of the ssh user on the foreign server. Default ENV['USER'].
244
+ | set :ssh_user, ENV['USER']
245
+ |---
246
+ | :identity_key
247
+ | The path to the key to use when ssh'ing into a foreign server.
248
+ | set :identity_key, ENV['HOME'] + "/.ssh/id_rsa"
249
+ |}
250
+
251
+ ==Rotate==
252
+ Rotation of your backups is a way to keep snapshot copies of your backups in time while not keeping every single backup for every single day.
253
+ Currently the only form of rotation Backup supports is [[grandfather-father-son]] See Appendix A if you are unfamiliar with how this works.
254
+
255
+ set :rotation_method, :gfs # this is the default. you don't need to set it, but this is how you could
256
+
257
+ By deafult, a <tt>son</tt> is created daily, unless it is a day to create a father or
258
+ grandfather. It is assumed that every time you run Backup you want to create a
259
+ backup. Therefore, if you do not want to a son etc, do not run the program.
260
+ You can specify when the son is promoted to a father by the following variable.
261
+
262
+ set :son_promoted_on, :fri
263
+
264
+ You specify when fathers are promoted to grandfathers by something like the following
265
+
266
+ set :father_promoted_on, :last_fri_of_the_month
267
+
268
+ Valid argumetns for specifying these promotions are as follows:
269
+ * :mon-:sun - A symbol of the abbreviation of any day of the week
270
+ * :last_*_of_the_month - A symbol, replacing the * with the abbreviation for the day of the weeks. Such as :last_fri_of_the_month.
271
+ * Any valid Runt object.
272
+
273
+ Representing these [[temporal ranges]] is done internally by using Runt. You are, therefore, allowed to pass in your own arbitrarily complex runt object.
274
+ Say for instance that I wanted to promote to fathers on monday, wednesday and friday. I could do something like the following:
275
+
276
+ mon_wed_fri = Runt::DIWeek.new(Runt::Mon) |
277
+ Runt::DIWeek.new(Runt::Wed) |
278
+ Runt::DIWeek.new(Runt::Fri)
279
+ set :son_promoted_on, mon_wed_fri
280
+
281
+ See the [[Runt documentation]] for more information on this.
282
+
283
+ You can set how many of each rank to keep:
284
+
285
+ set :sons_to_keep, 14
286
+ set :fathers_to_keep, 6
287
+ set :grandfathers_to_keep, 6
288
+
289
+ ==Examples==
290
+
291
+ Here we will cover three examples.
292
+ # a super-simple backup to a local directory, show how easy it is
293
+ # a more complex implementation, show the variables you can set show the customizability and use of foreign server
294
+ # every more complex. define your own method, use a global file to share in the configuration.
295
+
296
+ ===Example One: Backup folder of Logs===
297
+ Our first example will be backing up a folder of logs. Say we have a folder
298
+ '/var/my_logs/' and it is full of log files. It's full. Seriously, it's getting
299
+ stuffy in there.
300
+ Anyway, what we want is to:
301
+ * move out all the old log files
302
+ * compress them and store them in a local folder
303
+ * store 2 weeks of daily backups (sons)
304
+ * store a weekly backup (father) going back 6 weeks
305
+ * and create a monthly backup on the last friday of every month (grandfather) for 6 months
306
+
307
+ Thankfully, this is incredibly simple:
308
+
309
+ set :backup_path, "/var/local/backups/my_old_logs"
310
+ set :tmp_dir, "/tmp" # this is the default so you actually dont have to specify it
311
+ action :content, :is_contents_of => "/var/my_logs"
312
+
313
+ ''In this case, make sure that <tt>:backup_path</tt> and <tt>:tmp_dir</tt> are writable by the user
314
+ that is running the backup script.''
315
+
316
+ And thats it!
317
+
318
+ Note a few things here.
319
+ # Each time we <tt>set</tt> a variable that becomes available to the actions as <tt>c[:var]</tt>
320
+
321
+ ===Example Two: SQL Backup===
322
+ Our second example will be backing up a MediaWiki installation.
323
+ Say we have a MySQL database named 'mediawiki'.
324
+ What we want is to:
325
+ * create a dump of the database every day
326
+ * compress this backup and store it in a local folder
327
+ * store 2 weeks of daily backups (son) [same as last time]
328
+ * store "father" backups every monday,wednesday and friday going back 6 weeks
329
+ * and create a monthly backup on the last friday of every month (grandfather) for 6 months
330
+
331
+ Thankfully, this is incredibly simple:
332
+
333
+ set :backup_path, "/var/local/backups/mediawiki"
334
+
335
+ action(:content) do
336
+ dump = c[:tmp_dir] + "/mediawiki.sql"
337
+ sh "mysqldump -uroot mediawiki > #{dump}"
338
+ dump # make sure you return the name of the file
339
+ end
340
+
341
+ action :delivery, :method => :scp
342
+ action :rotate, :method => :via_ssh
343
+
344
+ set :servers, %w{ my.server.com }
345
+
346
+ set :son_promoted_on, :sun
347
+ set :father_promoted_on, :last_sun_of_the_month
348
+
349
+ set :sons_to_keep, 21
350
+ set :fathers_to_keep, 12
351
+ set :grandfathers_to_keep, 12
352
+
353
+ ===Example Three: Something more complex===
354
+
355
+ action :content, :is_file => "/path/to/file.abc"
356
+ action :compress, :method => :my_tar_gzip
357
+
358
+ action(:my_tar_gzip) do
359
+ name = c[:tmp_dir] + "/" + File.basename(last_result) + ".tar.gzip"
360
+ sh "tar -czv --exclude .DS* --exclude CVS #{last_result} > #{name}"
361
+ name # make sure you return the name of the
362
+ end
363
+
364
+ set :encrypt, true
365
+
366
+ action :deliver, :method => :scp
367
+ action :rotate, :method => :via_ssh
368
+
369
+ set :ssh_user, "backup_user"
370
+ set :identity_key, ENV['HOME'] + "/.ssh/backup_key"
371
+
372
+ * how to setup the cron job
373
+
374
+ ==TODO==
375
+
376
+ what is left to do:
377
+ * start testing it
378
+ * work on the styles
379
+ * lookup setup.rb files
380
+
381
+ ==TODO==
382
+ * Add in better logging
383
+
384
+ ==BUGS==
385
+ * You can't <tt>return</tt> in the user-defined actions for some reason. I think this
386
+ has to do with the <tt>instance_eval</tt>. But still, I wouldn't think it would
387
+ matter. I'd be interested in any suggestions on how to fix this.
data/bin/backup ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ $: << File.dirname(__FILE__) + "/../lib"
3
+
4
+ begin
5
+ require 'rubygems'
6
+ rescue LoadError
7
+ # no rubygems to load, so we fail silently
8
+ end
9
+
10
+ require 'backup/cli'
11
+
12
+ Backup::CLI.execute!
data/bin/commands.sh ADDED
@@ -0,0 +1,2 @@
1
+ #!/bin/bash
2
+ ./bin/backup --recipe examples/mediawiki.rb