phusion-backup 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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