backup 2.3.1 → 2.3.2.pre
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/CHANGELOG +16 -1
- data/README.textile +42 -177
- data/bin/backup +14 -17
- data/generators/backup/templates/config/backup.rb +26 -6
- data/generators/backup/templates/migrations/create_backup_tables.rb +3 -2
- data/generators/backup/templates/tasks/backup.rake +14 -17
- data/generators/backup_update/backup_update_generator.rb +50 -0
- data/generators/backup_update/templates/migrations/update_backup_tables.rb +27 -0
- data/lib/backup.rb +31 -30
- data/lib/backup/adapters/archive.rb +19 -54
- data/lib/backup/adapters/base.rb +55 -35
- data/lib/backup/adapters/custom.rb +15 -53
- data/lib/backup/adapters/mysql.rb +24 -55
- data/lib/backup/adapters/postgresql.rb +19 -54
- data/lib/backup/adapters/sqlite.rb +25 -0
- data/lib/backup/command_helper.rb +11 -0
- data/lib/backup/configuration/adapter.rb +4 -11
- data/lib/backup/configuration/adapter_options.rb +3 -14
- data/lib/backup/configuration/attributes.rb +19 -0
- data/lib/backup/configuration/base.rb +26 -9
- data/lib/backup/configuration/mail.rb +3 -9
- data/lib/backup/configuration/smtp.rb +3 -14
- data/lib/backup/configuration/storage.rb +3 -12
- data/lib/backup/connection/s3.rb +3 -1
- data/lib/backup/environment/unix.rb +4 -4
- data/lib/backup/mail/base.rb +8 -2
- data/lib/backup/mail/mail.txt +3 -3
- data/lib/backup/record/base.rb +65 -0
- data/lib/backup/record/ftp.rb +10 -69
- data/lib/backup/record/local.rb +26 -0
- data/lib/backup/record/s3.rb +9 -63
- data/lib/backup/record/scp.rb +9 -64
- data/lib/backup/record/sftp.rb +10 -68
- data/lib/backup/storage/ftp.rb +3 -1
- data/lib/backup/storage/local.rb +24 -0
- data/lib/backup/storage/s3.rb +3 -1
- data/lib/backup/storage/scp.rb +3 -1
- data/lib/backup/storage/sftp.rb +3 -1
- data/setup/backup.rb +27 -6
- data/setup/backup.sqlite3 +0 -0
- metadata +130 -60
- data/.document +0 -5
- data/.gitignore +0 -5
- data/Rakefile +0 -70
- data/backup.gemspec +0 -111
@@ -1,16 +1,10 @@
|
|
1
1
|
module Backup
|
2
2
|
module Configuration
|
3
3
|
class Mail
|
4
|
-
|
5
|
-
|
6
|
-
%w(from to smtp).each do |method|
|
7
|
-
define_method method do |value|
|
8
|
-
attributes[method.to_sym] = value
|
9
|
-
end
|
10
|
-
end
|
4
|
+
extend Backup::Configuration::Attributes
|
5
|
+
generate_attributes %w(from to smtp)
|
11
6
|
|
12
7
|
def initialize
|
13
|
-
@attributes = {}
|
14
8
|
@smtp_configuration = Backup::Configuration::SMTP.new
|
15
9
|
end
|
16
10
|
|
@@ -23,4 +17,4 @@ module Backup
|
|
23
17
|
end
|
24
18
|
end
|
25
19
|
end
|
26
|
-
end
|
20
|
+
end
|
@@ -1,19 +1,8 @@
|
|
1
1
|
module Backup
|
2
2
|
module Configuration
|
3
3
|
class SMTP
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
%w(host port username password authentication domain tls).each do |method|
|
8
|
-
define_method method do |value|
|
9
|
-
attributes[method.to_sym] = value
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def initialize
|
14
|
-
@attributes = {}
|
15
|
-
end
|
16
|
-
|
4
|
+
extend Backup::Configuration::Attributes
|
5
|
+
generate_attributes %w(host port username password authentication domain tls)
|
17
6
|
end
|
18
7
|
end
|
19
|
-
end
|
8
|
+
end
|
@@ -1,17 +1,8 @@
|
|
1
1
|
module Backup
|
2
2
|
module Configuration
|
3
3
|
class Storage
|
4
|
-
|
5
|
-
|
6
|
-
%w(ip user password path access_key_id secret_access_key use_ssl bucket).each do |method|
|
7
|
-
define_method method do |value|
|
8
|
-
attributes[method] = value
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def initialize
|
13
|
-
@attributes = {}
|
14
|
-
end
|
4
|
+
extend Backup::Configuration::Attributes
|
5
|
+
generate_attributes %w(ip user password path access_key_id secret_access_key use_ssl bucket)
|
15
6
|
end
|
16
7
|
end
|
17
|
-
end
|
8
|
+
end
|
data/lib/backup/connection/s3.rb
CHANGED
@@ -5,13 +5,13 @@ module Backup
|
|
5
5
|
require 'active_record'
|
6
6
|
require 'optparse'
|
7
7
|
|
8
|
-
# Sets BACKUP_PATH
|
9
|
-
BACKUP_PATH = "/opt/backup"
|
8
|
+
# Sets BACKUP_PATH
|
9
|
+
BACKUP_PATH = ENV['BACKUP_PATH'] || "/opt/backup"
|
10
10
|
|
11
11
|
# Sets DB_CONNECTION_SETTINGS
|
12
12
|
DB_CONNECTION_SETTINGS = {
|
13
13
|
:adapter => "sqlite3",
|
14
|
-
:database => "/
|
14
|
+
:database => "#{BACKUP_PATH}/backup.sqlite3",
|
15
15
|
:pool => 5,
|
16
16
|
:timeout => 5000
|
17
17
|
}
|
@@ -32,7 +32,7 @@ module Backup
|
|
32
32
|
|
33
33
|
1: Set up some "Backup Settings" inside the configuration file!
|
34
34
|
|
35
|
-
/
|
35
|
+
#{BACKUP_PATH}/config/backup.rb
|
36
36
|
|
37
37
|
|
38
38
|
2: Run the backups!
|
data/lib/backup/mail/base.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'pony'
|
2
|
+
|
1
3
|
module Backup
|
2
4
|
module Mail
|
3
5
|
class Base
|
@@ -77,8 +79,12 @@ module Backup
|
|
77
79
|
line.gsub!(':time', Time.now.strftime("%r"))
|
78
80
|
line.gsub!(':adapter', @backup.procedure.adapter_name.to_s)
|
79
81
|
line.gsub!(':location', bucket || path)
|
80
|
-
line.gsub!(':remote', bucket ? "Amazon S3" : "the remote server (#{ip})")
|
81
82
|
line.gsub!(':backup', @backup.final_file)
|
83
|
+
case @backup.procedure.storage_name.to_sym
|
84
|
+
when :s3 then line.gsub!(':remote', "on Amazon S3")
|
85
|
+
when :local then line.gsub!(':remote', "on the local server")
|
86
|
+
when :scp, :sftp, :ftp then line.gsub!(':remote', "on the remote server (#{ip})")
|
87
|
+
end
|
82
88
|
@content ||= String.new
|
83
89
|
@content << line
|
84
90
|
end
|
@@ -86,4 +92,4 @@ module Backup
|
|
86
92
|
|
87
93
|
end
|
88
94
|
end
|
89
|
-
end
|
95
|
+
end
|
data/lib/backup/mail/mail.txt
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
A backup was successfully created for ":trigger"!
|
1
|
+
A backup was successfully created for the trigger: ":trigger"!
|
2
2
|
|
3
|
-
The backup was created on ":day of :month :year at :time".
|
3
|
+
The backup was created on ":day of :month :year at :time", using the ":adapter" adapter.
|
4
4
|
|
5
|
-
|
5
|
+
The Backup was stored in ":location" :remote.
|
6
6
|
|
7
7
|
The following backup was stored: ":backup"
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Backup
|
2
|
+
module Record
|
3
|
+
class Base < ActiveRecord::Base
|
4
|
+
|
5
|
+
if DB_CONNECTION_SETTINGS
|
6
|
+
establish_connection(DB_CONNECTION_SETTINGS)
|
7
|
+
end
|
8
|
+
|
9
|
+
set_table_name 'backup'
|
10
|
+
|
11
|
+
default_scope :order => 'created_at desc'
|
12
|
+
|
13
|
+
# Callbacks
|
14
|
+
after_save :clean_backups
|
15
|
+
|
16
|
+
# Attributes
|
17
|
+
attr_accessor :adapter_config, :keep_backups
|
18
|
+
|
19
|
+
# Receives the options hash and stores it
|
20
|
+
def load_adapter(adapter)
|
21
|
+
self.adapter_config = adapter
|
22
|
+
self.trigger = adapter.procedure.trigger
|
23
|
+
self.adapter = adapter.procedure.adapter_name.to_s
|
24
|
+
self.filename = adapter.final_file
|
25
|
+
self.keep_backups = adapter.procedure.attributes['keep_backups']
|
26
|
+
|
27
|
+
# TODO calculate md5sum of file
|
28
|
+
load_specific_settings(adapter) if respond_to?(:load_specific_settings)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Destroys all backups for the specified trigger from Remote Server (FTP)
|
32
|
+
def self.destroy_all_backups(procedure, trigger)
|
33
|
+
backups = self.all(:conditions => {:trigger => trigger})
|
34
|
+
unless backups.empty?
|
35
|
+
# Derived classes must implement this method!
|
36
|
+
self.destroy_backups(procedure, backups)
|
37
|
+
|
38
|
+
puts "\nAll \"#{procedure.trigger}\" backups destroyed.\n\n"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
# Maintains the backup file amount on the remote server
|
45
|
+
# This is invoked after a successful record save
|
46
|
+
# This deletes the oldest files when the backup limit has been exceeded
|
47
|
+
def clean_backups
|
48
|
+
if keep_backups.is_a?(Integer)
|
49
|
+
backups = self.class.all(:conditions => {:trigger => trigger})
|
50
|
+
backups_to_destroy = backups[keep_backups, backups.size] || []
|
51
|
+
|
52
|
+
unless backups_to_destroy.empty?
|
53
|
+
# Derived classes must implement this method!
|
54
|
+
self.class.destroy_backups(adapter_config.procedure, backups_to_destroy)
|
55
|
+
|
56
|
+
puts "\nBackup storage for \"#{trigger}\" is limited to #{keep_backups} backups."
|
57
|
+
puts "\nThe #{keep_backups} most recent backups are now stored on the remote server.\n\n"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
data/lib/backup/record/ftp.rb
CHANGED
@@ -1,41 +1,20 @@
|
|
1
|
+
require 'net/ftp'
|
2
|
+
|
1
3
|
module Backup
|
2
4
|
module Record
|
3
|
-
class FTP <
|
4
|
-
|
5
|
-
if DB_CONNECTION_SETTINGS
|
6
|
-
establish_connection(DB_CONNECTION_SETTINGS)
|
7
|
-
end
|
8
|
-
|
9
|
-
set_table_name 'backup'
|
10
|
-
default_scope \
|
11
|
-
:order => 'created_at desc',
|
12
|
-
:conditions => {:storage => 'ftp'}
|
13
|
-
|
14
|
-
# Callbacks
|
15
|
-
after_save :clean_backups
|
5
|
+
class FTP < Backup::Record::Base
|
16
6
|
|
17
|
-
|
18
|
-
attr_accessor :adapter_config, :keep_backups, :ip, :user, :password
|
7
|
+
attr_accessor :ip, :user, :password
|
19
8
|
|
20
|
-
|
21
|
-
# Sets the FTP values
|
22
|
-
def load_adapter(adapter)
|
23
|
-
self.adapter_config = adapter
|
24
|
-
self.storage = 'ftp'
|
25
|
-
self.trigger = adapter.procedure.trigger
|
26
|
-
self.adapter = adapter.procedure.adapter_name.to_s
|
27
|
-
self.filename = adapter.final_file
|
28
|
-
self.keep_backups = adapter.procedure.attributes['keep_backups']
|
29
|
-
|
9
|
+
def load_specific_settings(adapter)
|
30
10
|
%w(ip user password path).each do |method|
|
31
11
|
send(:"#{method}=", adapter.procedure.get_storage_configuration.attributes[method])
|
32
12
|
end
|
33
13
|
end
|
34
14
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
unless backups.empty?
|
15
|
+
private
|
16
|
+
|
17
|
+
def self.destroy_backups(procedure, backups)
|
39
18
|
ip = procedure.get_storage_configuration.attributes['ip']
|
40
19
|
user = procedure.get_storage_configuration.attributes['user']
|
41
20
|
password = procedure.get_storage_configuration.attributes['password']
|
@@ -48,51 +27,13 @@ module Backup
|
|
48
27
|
ftp.delete(backup.filename)
|
49
28
|
backup.destroy
|
50
29
|
rescue
|
30
|
+
puts "Could not find backup #{backup.path}/#{backup.filename}."
|
51
31
|
backup.destroy
|
52
32
|
end
|
53
33
|
end
|
54
34
|
end
|
55
|
-
|
56
|
-
puts "\nAll \"#{trigger}\" backups destroyed.\n\n"
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
private
|
61
|
-
|
62
|
-
# Maintains the backup file amount on the remote server
|
63
|
-
# This is invoked after a successful record save
|
64
|
-
# This deletes the oldest files when the backup limit has been exceeded
|
65
|
-
def clean_backups
|
66
|
-
if keep_backups.is_a?(Integer)
|
67
|
-
backups = Backup::Record::FTP.all(:conditions => {:trigger => trigger})
|
68
|
-
backups_to_destroy = Array.new
|
69
|
-
backups.each_with_index do |backup, index|
|
70
|
-
if index >= keep_backups then
|
71
|
-
backups_to_destroy << backup
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
unless backups_to_destroy.empty?
|
76
|
-
Net::FTP.open(ip, user, password) do |ftp|
|
77
|
-
backups_to_destroy.each do |backup|
|
78
|
-
puts "\nDestroying backup \"#{backup.filename}\" from path \"#{backup.path}\"."
|
79
|
-
begin
|
80
|
-
ftp.chdir(backup.path)
|
81
|
-
ftp.delete(backup.filename)
|
82
|
-
backup.destroy
|
83
|
-
rescue
|
84
|
-
puts "Could not find backup #{backup.path}/#{backup.filename}.."
|
85
|
-
backup.destroy
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
puts "\nBackup storage for \"#{trigger}\" is limited to #{keep_backups} backups."
|
91
|
-
puts "\nThe #{keep_backups} most recent backups are now stored on the remote server.\n\n"
|
92
|
-
end
|
93
|
-
end
|
94
35
|
end
|
95
36
|
|
96
37
|
end
|
97
38
|
end
|
98
|
-
end
|
39
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Backup
|
2
|
+
module Record
|
3
|
+
class Local < Backup::Record::Base
|
4
|
+
|
5
|
+
def load_specific_settings(adapter)
|
6
|
+
self.path = adapter.procedure.get_storage_configuration.attributes['path']
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
class << self
|
12
|
+
include Backup::CommandHelper
|
13
|
+
|
14
|
+
def destroy_backups(procedure, backups)
|
15
|
+
backups.each do |backup|
|
16
|
+
puts "\nDestroying backup \"#{backup.filename}\" from path \"#{backup.path}\"."
|
17
|
+
run "rm #{File.join(backup.path, backup.filename)}"
|
18
|
+
backup.destroy
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
data/lib/backup/record/s3.rb
CHANGED
@@ -1,38 +1,16 @@
|
|
1
|
+
require 'backup/connection/s3'
|
2
|
+
|
1
3
|
module Backup
|
2
4
|
module Record
|
3
|
-
class S3 <
|
5
|
+
class S3 < Backup::Record::Base
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
+
def load_specific_settings(adapter)
|
8
|
+
self.bucket = adapter.procedure.get_storage_configuration.attributes['bucket']
|
7
9
|
end
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
:conditions => {:storage => 's3'}
|
13
|
-
|
14
|
-
# Callbacks
|
15
|
-
after_save :clean_backups
|
16
|
-
|
17
|
-
# Attributes
|
18
|
-
attr_accessor :adapter_config, :keep_backups
|
19
|
-
|
20
|
-
# Receives the options hash and stores it
|
21
|
-
# Sets the S3 values
|
22
|
-
def load_adapter(adapter)
|
23
|
-
self.adapter_config = adapter
|
24
|
-
self.storage = 's3'
|
25
|
-
self.trigger = adapter.procedure.trigger
|
26
|
-
self.adapter = adapter.procedure.adapter_name.to_s
|
27
|
-
self.filename = adapter.final_file
|
28
|
-
self.bucket = adapter.procedure.get_storage_configuration.attributes['bucket']
|
29
|
-
self.keep_backups = adapter.procedure.attributes['keep_backups']
|
30
|
-
end
|
31
|
-
|
32
|
-
# Destroys all backups for the specified trigger from Amazon S3
|
33
|
-
def self.destroy_all_backups(procedure, trigger)
|
34
|
-
backups = Backup::Record::S3.all(:conditions => {:trigger => trigger})
|
35
|
-
unless backups.empty?
|
11
|
+
private
|
12
|
+
|
13
|
+
def self.destroy_backups(procedure, backups)
|
36
14
|
s3 = Backup::Connection::S3.new
|
37
15
|
s3.static_initialize(procedure)
|
38
16
|
s3.connect
|
@@ -41,40 +19,8 @@ module Backup
|
|
41
19
|
s3.destroy(backup.filename, backup.bucket)
|
42
20
|
backup.destroy
|
43
21
|
end
|
44
|
-
puts "\nAll \"#{trigger}\" backups destroyed.\n\n"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
private
|
49
|
-
|
50
|
-
# Maintains the backup file amount on S3
|
51
|
-
# This is invoked after a successful record save
|
52
|
-
# This deletes the oldest files when the backup limit has been exceeded
|
53
|
-
def clean_backups
|
54
|
-
if keep_backups.is_a?(Integer)
|
55
|
-
backups = Backup::Record::S3.all(:conditions => {:trigger => trigger})
|
56
|
-
backups_to_destroy = Array.new
|
57
|
-
backups.each_with_index do |backup, index|
|
58
|
-
if index >= keep_backups then
|
59
|
-
backups_to_destroy << backup
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
unless backups_to_destroy.empty?
|
64
|
-
s3 = Backup::Connection::S3.new(adapter_config)
|
65
|
-
s3.connect
|
66
|
-
backups_to_destroy.each do |backup|
|
67
|
-
puts "\nDestroying backup \"#{backup.filename}\" from bucket \"#{backup.bucket}\"."
|
68
|
-
s3.destroy(backup.filename, backup.bucket)
|
69
|
-
backup.destroy
|
70
|
-
end
|
71
|
-
|
72
|
-
puts "\nBackup storage for \"#{trigger}\" is limited to #{keep_backups} backups."
|
73
|
-
puts "\nThe #{keep_backups} most recent backups are now stored on S3.\n\n"
|
74
|
-
end
|
75
|
-
end
|
76
22
|
end
|
77
23
|
|
78
24
|
end
|
79
25
|
end
|
80
|
-
end
|
26
|
+
end
|
data/lib/backup/record/scp.rb
CHANGED
@@ -1,41 +1,20 @@
|
|
1
|
+
require 'net/scp'
|
2
|
+
|
1
3
|
module Backup
|
2
4
|
module Record
|
3
|
-
class SCP <
|
4
|
-
|
5
|
-
if DB_CONNECTION_SETTINGS
|
6
|
-
establish_connection(DB_CONNECTION_SETTINGS)
|
7
|
-
end
|
5
|
+
class SCP < Backup::Record::Base
|
8
6
|
|
9
|
-
|
10
|
-
default_scope \
|
11
|
-
:order => 'created_at desc',
|
12
|
-
:conditions => {:storage => 'scp'}
|
13
|
-
|
14
|
-
# Callbacks
|
15
|
-
after_save :clean_backups
|
16
|
-
|
17
|
-
# Attributes
|
18
|
-
attr_accessor :adapter_config, :keep_backups, :ip, :user, :password
|
7
|
+
attr_accessor :ip, :user, :password
|
19
8
|
|
20
|
-
|
21
|
-
# Sets the SCP values
|
22
|
-
def load_adapter(adapter)
|
23
|
-
self.adapter_config = adapter
|
24
|
-
self.storage = 'scp'
|
25
|
-
self.trigger = adapter.procedure.trigger
|
26
|
-
self.adapter = adapter.procedure.adapter_name.to_s
|
27
|
-
self.filename = adapter.final_file
|
28
|
-
self.keep_backups = adapter.procedure.attributes['keep_backups']
|
29
|
-
|
9
|
+
def load_specific_settings(adapter)
|
30
10
|
%w(ip user password path).each do |method|
|
31
11
|
send(:"#{method}=", adapter.procedure.get_storage_configuration.attributes[method])
|
32
12
|
end
|
33
13
|
end
|
34
14
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
unless backups.empty?
|
15
|
+
private
|
16
|
+
|
17
|
+
def self.destroy_backups(procedure, backups)
|
39
18
|
ip = procedure.get_storage_configuration.attributes['ip']
|
40
19
|
user = procedure.get_storage_configuration.attributes['user']
|
41
20
|
password = procedure.get_storage_configuration.attributes['password']
|
@@ -47,42 +26,8 @@ module Backup
|
|
47
26
|
backup.destroy
|
48
27
|
end
|
49
28
|
end
|
50
|
-
puts "\nAll \"#{trigger}\" backups destroyed.\n\n"
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
private
|
55
|
-
|
56
|
-
# Maintains the backup file amount on the remote server
|
57
|
-
# This is invoked after a successful record save
|
58
|
-
# This deletes the oldest files when the backup limit has been exceeded
|
59
|
-
def clean_backups
|
60
|
-
if keep_backups.is_a?(Integer)
|
61
|
-
backups = Backup::Record::SCP.all(:conditions => {:trigger => trigger})
|
62
|
-
backups_to_destroy = Array.new
|
63
|
-
backups.each_with_index do |backup, index|
|
64
|
-
if index >= keep_backups then
|
65
|
-
backups_to_destroy << backup
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
unless backups_to_destroy.empty?
|
70
|
-
|
71
|
-
Net::SSH.start(ip, user, :password => password) do |ssh|
|
72
|
-
backups_to_destroy.each do |backup|
|
73
|
-
puts "\nDestroying backup \"#{backup.filename}\" from path \"#{backup.path}\"."
|
74
|
-
ssh.exec("rm #{File.join(backup.path, backup.filename)}")
|
75
|
-
backup.destroy
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
puts "\nBackup storage for \"#{trigger}\" is limited to #{keep_backups} backups."
|
80
|
-
puts "\nThe #{keep_backups} most recent backups are now stored on the remote server.\n\n"
|
81
|
-
|
82
|
-
end
|
83
|
-
end
|
84
29
|
end
|
85
30
|
|
86
31
|
end
|
87
32
|
end
|
88
|
-
end
|
33
|
+
end
|