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.
- data/bin/phusion-backup +115 -14
- data/phusion-backup.gemspec +2 -2
- data/resources/default-files.txt +6 -0
- data/resources/default-install-script.sh +77 -0
- data/resources/default-postrestore.sh +12 -0
- data/resources/footer.sh +5 -0
- data/resources/header.sh +36 -0
- metadata +8 -5
- data/resources/default-install-script.txt +0 -6
data/bin/phusion-backup
CHANGED
@@ -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.
|
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
|
-
|
371
|
-
|
372
|
-
|
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
|
data/phusion-backup.gemspec
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "phusion-backup"
|
3
|
-
s.version = "1.0.
|
3
|
+
s.version = "1.0.3"
|
4
4
|
s.authors = ["Hongli Lai"]
|
5
|
-
s.date = "2011-03-
|
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"
|
data/resources/default-files.txt
CHANGED
@@ -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
|
data/resources/footer.sh
ADDED
data/resources/header.sh
ADDED
@@ -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:
|
4
|
+
hash: 17
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 1.0.
|
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-
|
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.
|
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: []
|