phusion-backup 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -83,7 +83,8 @@ class Core
83
83
 
84
84
  def generate(dir)
85
85
  copy_file_no_overwrite("#{ROOT}/resources/default-files.txt", "#{dir}/files.txt")
86
- copy_file_no_overwrite("#{ROOT}/resources/default-install-script.txt", "#{dir}/install-script.txt")
86
+ copy_file_no_overwrite("#{ROOT}/resources/default-install-script.sh", "#{dir}/install-script.sh")
87
+ copy_file_no_overwrite("#{ROOT}/resources/default-postrestore.sh", "#{dir}/postrestore.sh")
87
88
  end
88
89
 
89
90
  def run_backup(server)
@@ -179,6 +180,61 @@ class Core
179
180
  "old backups, more than #{MIN_BACKUPS_TO_KEEP} backups must exist."
180
181
  end
181
182
  end
183
+
184
+ def run_restore(server)
185
+ if !File.exist?("#{server.dir}/data")
186
+ puts "<red>No `data` subdirectory found in this backup directory.</red>"
187
+ puts
188
+ puts "This means that you either don't have a backup, or you specified the wrong directory."
189
+ exit 1
190
+ end
191
+
192
+ if File.exist?("#{server.dir}/install-script.sh")
193
+ script = "/tmp/script-#{Process.pid}.txt"
194
+ begin
195
+ File.open(script, 'w') do |f|
196
+ f.puts File.read("#{ROOT}/resources/header.sh")
197
+ f.puts File.read("#{server.dir}/install-script.sh")
198
+ f.puts File.read("#{ROOT}/resources/footer.sh")
199
+ end
200
+ sh! "scp", script, "root@#{server.hostname}:/tmp/script.sh"
201
+ sh! "ssh", "-t", "root@#{server.hostname}",
202
+ "bash /tmp/script.sh && " +
203
+ "rm -f /tmp/script.sh"
204
+ ensure
205
+ File.unlink(script) rescue nil
206
+ end
207
+ end
208
+
209
+ sh! 'ssh', "root@#{server.hostname}",
210
+ "mkdir -p /backup-tmp"
211
+ sh! 'rdiff-backup',
212
+ '--restore-as-of', 'now',
213
+ '--force',
214
+ '-v5',
215
+ '--print-statistics',
216
+ "#{server.dir}/data",
217
+ "root@#{server.hostname}::/backup-tmp"
218
+ sh! 'ssh', "root@#{server.hostname}",
219
+ "rsync -avz /backup-tmp/ / && chmod 700 /backup-tmp"
220
+
221
+ if File.exist?("#{server.dir}/postrestore.sh")
222
+ script = "/tmp/script-#{Process.pid}.txt"
223
+ begin
224
+ File.open(script, 'w') do |f|
225
+ f.puts File.read("#{ROOT}/resources/header.sh")
226
+ f.puts File.read("#{server.dir}/postrestore.sh")
227
+ f.puts File.read("#{ROOT}/resources/footer.sh")
228
+ end
229
+ sh! "scp", script, "root@#{server.hostname}:/tmp/script.sh"
230
+ sh! "ssh", "-t", "root@#{server.hostname}",
231
+ "bash /tmp/script.sh && " +
232
+ "rm -f /tmp/script.sh"
233
+ ensure
234
+ File.unlink(script) rescue nil
235
+ end
236
+ end
237
+ end
182
238
 
183
239
  private
184
240
  class CommandError < StandardError
@@ -290,6 +346,10 @@ class App
290
346
  opts.separator " phusion-backup --list"
291
347
  opts.separator ""
292
348
 
349
+ opts.separator "Restore the most recent backup:"
350
+ opts.separator " phusion-backup --restore hostname"
351
+ opts.separator ""
352
+
293
353
  opts.separator "Please read the README for tutorial!"
294
354
  opts.separator ""
295
355
  opts.separator "Available options:"
@@ -303,6 +363,10 @@ class App
303
363
  "in the given directory.") do |dir|
304
364
  options[:generate] = dir
305
365
  end
366
+ opts.on("--restore",
367
+ "Enable restore mode") do
368
+ options[:restore] = true
369
+ end
306
370
  opts.on("-h", "--help", "Show this help message.") do
307
371
  options[:help] = true
308
372
  end
@@ -321,25 +385,36 @@ class App
321
385
  return 0
322
386
  end
323
387
 
324
- core = Core.new(["#{Core::ROOT}/backups", "#{home_dir}/Backups"])
388
+ @core = Core.new(["#{Core::ROOT}/backups", "#{home_dir}/Backups"])
325
389
 
326
390
  if options[:list]
327
- core.servers.each do |server|
391
+ @core.servers.each do |server|
328
392
  printf "%-35s %s\n", server.hostname, server.dir
329
393
  end
330
394
  return 0
331
395
  elsif options[:generate]
332
- core.generate(options[:generate])
396
+ @core.generate(options[:generate])
397
+ return 0
398
+ elsif options[:restore]
399
+ run_in_restore_mode
400
+ return 0
401
+ else
402
+ run_in_backup_mode
333
403
  return 0
334
404
  end
335
-
405
+ rescue Core::CommandError
406
+ return 1
407
+ end
408
+
409
+ private
410
+ def run_in_backup_mode
336
411
  if @argv.empty?
337
- if core.servers.empty?
412
+ if @core.servers.empty?
338
413
  puts_error "You must create a backup specification first. Please read README for tutorial."
339
414
  else
340
415
  puts_error "Please specify the server you want to backup:"
341
416
  puts
342
- core.servers.each do |server|
417
+ @core.servers.each do |server|
343
418
  puts " phusion-backup #{server.hostname}"
344
419
  end
345
420
  puts
@@ -350,7 +425,7 @@ class App
350
425
 
351
426
  servers = []
352
427
  @argv.each do |name|
353
- server = core.find_server(name)
428
+ server = @core.find_server(name)
354
429
  if !server
355
430
  puts_error "This program doesn't know anything about the server '#{name}'."
356
431
  puts "If you've misspelled the name, please correct it."
@@ -363,16 +438,42 @@ class App
363
438
 
364
439
  servers.each do |server|
365
440
  puts "<banner>Backing up #{server.hostname} - #{server.dir}</banner>"
366
- core.run_backup(server)
441
+ @core.run_backup(server)
367
442
  puts
368
443
  end
444
+ end
445
+
446
+ def run_in_restore_mode
447
+ if @argv.empty?
448
+ if @core.servers.empty?
449
+ puts_error "Please specify the host name of the server you want to backup, " +
450
+ "or specify the path to the backup directory."
451
+ else
452
+ puts_error "Please specify the server you want to restore:"
453
+ puts
454
+ @core.servers.each do |server|
455
+ puts " phusion-backup --restore #{server.hostname}"
456
+ end
457
+ puts
458
+ puts "For full usage please see `phusion-backup --help` and the README."
459
+ end
460
+ return 1
461
+ elsif @argv.size > 1
462
+ puts_error "You can only specify one server when using --restore."
463
+ return 1
464
+ end
369
465
 
370
- return 0
371
- rescue Core::CommandError
372
- return 1
466
+ server = @core.find_server(@argv[0])
467
+ if !server
468
+ puts_error "This program doesn't know anything about the server '#{@argv[0]}'."
469
+ puts "If you've misspelled the name, please correct it."
470
+ puts "If you want to see a list of available servers that this programs knows about, run <b>phusion-backup --list</b>."
471
+ puts "For general, please refer to the README."
472
+ exit 1
473
+ end
474
+ @core.run_restore(server)
373
475
  end
374
-
375
- private
476
+
376
477
  def home_dir
377
478
  return Etc.getpwuid(Process.uid).dir
378
479
  end
@@ -1,8 +1,8 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "phusion-backup"
3
- s.version = "1.0.2"
3
+ s.version = "1.0.3"
4
4
  s.authors = ["Hongli Lai"]
5
- s.date = "2011-03-30"
5
+ s.date = "2011-03-31"
6
6
  s.description = "Simple backup tool utilizing rdiff-backup."
7
7
  s.summary = "Simple backup tool utilizing rdiff-backup."
8
8
  s.email = "hongli@phusion.nl"
@@ -1,3 +1,7 @@
1
+ ## This file specifies which files on the server should be backed up.
2
+ ## Filenames may be globs. A '-' prefix means that the glob is excluded
3
+ ## from backup.
4
+
1
5
  # Standard system stuff.
2
6
  /etc/skel
3
7
  /etc/profile
@@ -6,6 +10,8 @@
6
10
  /etc/nanorc
7
11
  /etc/screenrc
8
12
  /etc/mailname
13
+ /etc/exim4
14
+ /etc/postfix
9
15
  /etc/rc.local
10
16
  /var/spool/cron
11
17
 
@@ -0,0 +1,77 @@
1
+ ## The commands in this file are run upon restoring to a server,
2
+ ## before any files are copied over. This is a normal shell script,
3
+ ## run in bash. Please ensure that all commands run here are idempotent!!
4
+ ##
5
+ ## By default, all debconf questions are postponed until the end
6
+ ## so that you can answer everything at once without delaying the
7
+ ## install.
8
+
9
+ # Standard, essential tools
10
+ apt-get update
11
+ apt-get -y upgrade
12
+ apt-get install -y \
13
+ bash-completion screen wget gdebi-core \
14
+ rsync rdiff-backup
15
+
16
+ # Daemon tools
17
+ apt-get install -y daemontools daemontools-run
18
+
19
+ # Compiler toolchain
20
+ apt-get install -y build-essential gdb zlib1g-dev
21
+
22
+ # SQL databases
23
+ if true; then
24
+ # MySQL
25
+ DEBIAN_FRONTEND=noninteractive apt-get install -y mysql-server libmysqlclient-dev
26
+ package_name=$(dpkg-query -p mysql-server | grep Depends | grep -oEi 'mysql-server-[0-9a-z\.]+')
27
+ run_at_end dpkg-reconfigure $package_name
28
+
29
+ # SQLite3
30
+ apt-get install -y sqlite3 libsqlite3-dev
31
+ fi
32
+
33
+ # Email support
34
+ if true; then
35
+ # Exim
36
+ DEBIAN_FRONTEND=noninteractive apt-get install -y exim4
37
+ run_at_end dpkg-reconfigure -p medium exim4-config
38
+
39
+ # Postfix
40
+ # DEBIAN_FRONTEND=noninteractive apt-get install -y postfix
41
+ # run_at_end dpkg-reconfigure -p medium postfix
42
+ fi
43
+
44
+ # Ruby Enterprise Edition
45
+ if true; then
46
+ # basename=ruby-enterprise_1.8.7-2011.03_i386_ubuntu10.04.deb
47
+ # basename=ruby-enterprise_1.8.7-2011.03_amd64_ubuntu10.04.deb
48
+ # basename=ruby-enterprise_1.8.7-2011.03_amd64_debian5.0.deb
49
+ basename=ruby-enterprise_1.8.7-2011.03_amd64_debian6.0.deb
50
+ if [[ ! -f /usr/local/bin/ruby ]]; then
51
+ rm -f $basename
52
+ wget http://rubyenterpriseedition.googlecode.com/files/$basename
53
+ gdebi -n $basename
54
+ rm -f $basename
55
+ fi
56
+ fi
57
+
58
+ # Install users
59
+ if true; then
60
+ # Specify list of usernames here, separated by space.
61
+ # Each user will be created with a random password.
62
+ # It's up to you to change the passwords later.
63
+ # USERNAMES="john jane"
64
+ USERNAMES=""
65
+
66
+ for user in $USERNAMES; do
67
+ if ! grep -q "^$user:" /etc/passwd; then
68
+ password=$(tr -dc A-Za-z0-9 < /dev/urandom | (head -c $1 > /dev/null 2>&1 || head -c 15))
69
+ adduser $user < /dev/null
70
+ echo
71
+ echo "$user:$password" | chpasswd
72
+ fi
73
+ done
74
+ fi
75
+
76
+ # Configure time zone
77
+ dpkg-reconfigure tzdata
@@ -0,0 +1,12 @@
1
+ ## The commands in this file are run upon restoring to a server,
2
+ ## after install-script.sh is run and after files are copied over.
3
+ ## This is a normal shell script, run in bash. Please ensure that
4
+ ## all commands run here are idempotent!!
5
+
6
+ # Disable all daemon tools services until explicitly enabled by administrator.
7
+ if [[ -f /usr/bin/svc ]]; then
8
+ services=$(/bin/ls -1 /etc/service)
9
+ if [[ ${#services[@]} > 0 ]] && ! [[ ${#services[@]} = 1 && ${servers[0]} = "" ]]; then
10
+ svc -d /etc/service/*
11
+ fi
12
+ fi
@@ -0,0 +1,5 @@
1
+ set +v
2
+ echo "------------------------------------------"
3
+ set -v
4
+
5
+ run_end_commands
@@ -0,0 +1,36 @@
1
+ NRUN_AT_END=0
2
+
3
+ function set_variable {
4
+ local name="$1"
5
+ shift
6
+ local value=("$@")
7
+ set +v
8
+ eval "$name=(\"\${value[@]}\")"
9
+ set -v
10
+ }
11
+
12
+ function run_at_end {
13
+ set_variable "RUN_AT_END_$NRUN_AT_END" "$@"
14
+ set +e
15
+ (( NRUN_AT_END++ ))
16
+ set -e
17
+ }
18
+
19
+ function run_end_commands {
20
+ set +v
21
+ local i=0
22
+ local name
23
+ local value
24
+ while [[ $i -lt $NRUN_AT_END ]]; do
25
+ name="RUN_AT_END_$i"
26
+ eval "value=(\"\${$name[@]}\")"
27
+ echo "${value[@]}"
28
+ "${value[@]}"
29
+ set +e
30
+ (( i++ ))
31
+ set -e
32
+ done
33
+ set -v
34
+ }
35
+
36
+ set -ev
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phusion-backup
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 17
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
- - 2
10
- version: 1.0.2
9
+ - 3
10
+ version: 1.0.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Hongli Lai
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-03-30 00:00:00 +02:00
18
+ date: 2011-03-31 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -47,7 +47,10 @@ files:
47
47
  - phusion-backup.gemspec
48
48
  - bin/phusion-backup
49
49
  - resources/default-files.txt
50
- - resources/default-install-script.txt
50
+ - resources/default-install-script.sh
51
+ - resources/default-postrestore.sh
52
+ - resources/footer.sh
53
+ - resources/header.sh
51
54
  has_rdoc: true
52
55
  homepage: https://github.com/FooBarWidget/crash-watch
53
56
  licenses: []
@@ -1,6 +0,0 @@
1
- # Standard, essential tools
2
- apt-get install bash-completion screen
3
- apt-get install rdiff-backup python-pylibacl-dbg python-pyxattr-dbg
4
-
5
- # Compiler toolchain
6
- apt-get install build-essential gdb