shnell 0.2.7 → 0.3.0
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/VERSION +1 -1
- data/bin/shnell +38 -12
- data/lib/shnell.rb +26 -0
- data/lib/shnell/actions/database.rb +12 -0
- data/lib/shnell/actions/ftp.rb +27 -0
- data/lib/shnell/backup.rb +108 -0
- data/lib/shnell/config.rb +59 -0
- metadata +7 -4
- data/lib/backup.rb +0 -163
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.3.0
|
data/bin/shnell
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
require 'rubygems'
|
|
4
4
|
require 'commander/import'
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
require
|
|
5
|
+
|
|
6
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
|
7
|
+
require 'shnell'
|
|
8
8
|
|
|
9
9
|
program :name, 'shnell'
|
|
10
10
|
program :version, File.read(File.join(File.dirname(__FILE__), '../VERSION'))
|
|
@@ -16,8 +16,7 @@ default_command :help
|
|
|
16
16
|
SCRIPTS_ROOT = Pathname.new(Dir.pwd)
|
|
17
17
|
CONFIG_FILENAME = File.join(SCRIPTS_ROOT, "config.yml")
|
|
18
18
|
|
|
19
|
-
include
|
|
20
|
-
include Backup
|
|
19
|
+
include Shnell
|
|
21
20
|
|
|
22
21
|
def scripts(pattern = nil)
|
|
23
22
|
if pattern
|
|
@@ -102,19 +101,19 @@ command :run do |c|
|
|
|
102
101
|
behavior = :skip if options.skip
|
|
103
102
|
behavior = :pretend if options.pretend
|
|
104
103
|
behavior = :force if options.force
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
Shnell.behavior = behavior
|
|
105
|
+
Shnell.quiet = options.quiet
|
|
107
106
|
|
|
108
107
|
if script == "all"
|
|
109
108
|
pattern = args.shift
|
|
110
109
|
|
|
111
110
|
scripts(pattern).each do |file|
|
|
112
111
|
say_script file, "Running", options.quiet
|
|
113
|
-
|
|
112
|
+
Shnell.source_root = file.sub(/\.rb$/, '')
|
|
114
113
|
require file
|
|
115
114
|
end
|
|
116
115
|
elsif script
|
|
117
|
-
|
|
116
|
+
Shnell.source_root = File.join(SCRIPTS_ROOT, script)
|
|
118
117
|
require script
|
|
119
118
|
else
|
|
120
119
|
say "No script set."
|
|
@@ -131,8 +130,8 @@ command :backup do |c|
|
|
|
131
130
|
c.action do |args, options|
|
|
132
131
|
script = args.shift
|
|
133
132
|
|
|
134
|
-
|
|
135
|
-
|
|
133
|
+
Shnell.quiet = options.quiet
|
|
134
|
+
Shnell.behavior = :backup
|
|
136
135
|
|
|
137
136
|
if script == "all"
|
|
138
137
|
pattern = args.shift
|
|
@@ -142,7 +141,34 @@ command :backup do |c|
|
|
|
142
141
|
require file
|
|
143
142
|
end
|
|
144
143
|
elsif script
|
|
145
|
-
require script
|
|
144
|
+
require File.join(script, 'backup.rb')
|
|
145
|
+
else
|
|
146
|
+
say "No backup script set."
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
command :restore do |c|
|
|
152
|
+
c.syntax = 'shnell restore script'
|
|
153
|
+
c.description = 'Restore a backup.'
|
|
154
|
+
|
|
155
|
+
c.option '-q', '--quiet', 'Supress status output'
|
|
156
|
+
|
|
157
|
+
c.action do |args, options|
|
|
158
|
+
script = args.shift
|
|
159
|
+
|
|
160
|
+
Shnell.quiet = options.quiet
|
|
161
|
+
Shnell.behavior = :restore
|
|
162
|
+
|
|
163
|
+
if script == "all"
|
|
164
|
+
pattern = args.shift
|
|
165
|
+
|
|
166
|
+
backup_scripts(pattern).each do |file|
|
|
167
|
+
say_script file, "Restore", options.quiet
|
|
168
|
+
require file
|
|
169
|
+
end
|
|
170
|
+
elsif script
|
|
171
|
+
require File.join(script, 'backup.rb')
|
|
146
172
|
else
|
|
147
173
|
say "No backup script set."
|
|
148
174
|
end
|
data/lib/shnell.rb
CHANGED
|
@@ -1,2 +1,28 @@
|
|
|
1
|
+
require 'filander'
|
|
2
|
+
require 'shnell/config'
|
|
3
|
+
require 'shnell/actions/ftp'
|
|
4
|
+
require 'shnell/actions/database'
|
|
5
|
+
require 'shnell/backup'
|
|
6
|
+
|
|
1
7
|
module Shnell
|
|
8
|
+
include Config
|
|
9
|
+
include Filander
|
|
10
|
+
include Ftp
|
|
11
|
+
include Database
|
|
12
|
+
include Backup
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
def behavior=(value)
|
|
16
|
+
Filander.behavior = value
|
|
17
|
+
Backup.behavior = value
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def quiet=(value)
|
|
21
|
+
Filander.quiet = value
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def source_root=(value)
|
|
25
|
+
Filander.source_root = value
|
|
26
|
+
end
|
|
27
|
+
end
|
|
2
28
|
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module Shnell
|
|
2
|
+
module Database
|
|
3
|
+
include Config
|
|
4
|
+
include Filander::Base
|
|
5
|
+
|
|
6
|
+
def create_database(name, user, password)
|
|
7
|
+
report :create_db, name
|
|
8
|
+
system "mysqladmin #{db_credentials} create #{name}"
|
|
9
|
+
system "mysql #{db_credentials} -e \"GRANT ALL ON #{name}.* TO '#{user}'@'localhost' IDENTIFIED BY '#{password}'\""
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'net/ftp'
|
|
2
|
+
|
|
3
|
+
module Shnell
|
|
4
|
+
module Ftp
|
|
5
|
+
include Config
|
|
6
|
+
include Filander::Base
|
|
7
|
+
|
|
8
|
+
def ftp_get(filename, destination)
|
|
9
|
+
return if Filander.behavior == :pretend
|
|
10
|
+
inside destination do
|
|
11
|
+
Net::FTP.open(ftp_host) do |ftp|
|
|
12
|
+
ftp.login ftp_user, ftp_password
|
|
13
|
+
ftp.getbinaryfile filename
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
yield if block_given? && File.exists?(File.join(destination, filename))
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def ftp_put(filename, destination = '/')
|
|
20
|
+
return if Filander.behavior == :pretend
|
|
21
|
+
Net::FTP.open(ftp_host) do |ftp|
|
|
22
|
+
ftp.login ftp_user, ftp_password
|
|
23
|
+
ftp.putbinaryfile File.join(destination, filename)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
module Shnell
|
|
2
|
+
module Backup
|
|
3
|
+
class << self
|
|
4
|
+
attr_accessor :behavior
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class BackupScript
|
|
8
|
+
include Config
|
|
9
|
+
include Ftp
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
def backup(name, &block)
|
|
13
|
+
backup = self.new(name)
|
|
14
|
+
backup.prepare
|
|
15
|
+
backup.instance_eval(&block)
|
|
16
|
+
backup.backup!
|
|
17
|
+
backup.finish
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def restore(name, &block)
|
|
21
|
+
backup = self.new(name)
|
|
22
|
+
backup.instance_eval(&block)
|
|
23
|
+
backup.restore!
|
|
24
|
+
backup.finish
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def initialize(service)
|
|
29
|
+
@service_root = service
|
|
30
|
+
@service_name = File.basename(service)
|
|
31
|
+
@database = @service_name.gsub(/[-\.]/, '_')
|
|
32
|
+
@tempdir = File.join("/tmp", @service_name)
|
|
33
|
+
@tarball = "#{@tempdir}.tar.bz2"
|
|
34
|
+
@directories = []
|
|
35
|
+
@databases = []
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def prepare
|
|
39
|
+
backup_cmd "mkdir -p #{@tempdir}"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def directory(filename)
|
|
43
|
+
@directories << filename
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def database(database = @database)
|
|
47
|
+
@databases << database
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def backup!
|
|
51
|
+
@directories.each do |filename|
|
|
52
|
+
report :directory, filename
|
|
53
|
+
filename = File.join(@service_root, filename)
|
|
54
|
+
backup_cmd "cp -r #{filename} #{@tempdir}/"
|
|
55
|
+
end
|
|
56
|
+
@databases.each do |database|
|
|
57
|
+
report :database, database
|
|
58
|
+
backup_cmd "mysqldump #{db_credentials} #{database} > #{File.join(@tempdir, "#{database}.sql")}"
|
|
59
|
+
end
|
|
60
|
+
backup_cmd "tar -C /tmp -cjf #{@tarball} #{@service_name}"
|
|
61
|
+
ftp_put @tarball
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def restore!
|
|
65
|
+
ftp_get File.basename(@tarball), "/tmp" do
|
|
66
|
+
backup_cmd "tar -C /tmp -xf #{@tarball}"
|
|
67
|
+
@databases.each do |database|
|
|
68
|
+
report :database, database
|
|
69
|
+
backup_cmd "mysql -u#{db_user} #{"-p#{db_password}" if db_password != ''} #{database} < #{File.join(@tempdir, "#{database}.sql")}"
|
|
70
|
+
end
|
|
71
|
+
@directories.each do |filename|
|
|
72
|
+
report :directory, filename
|
|
73
|
+
source = File.join(@tempdir, filename)
|
|
74
|
+
dest = File.join(@service_root, filename)
|
|
75
|
+
backup_cmd "cp -r #{source} #{dest}"
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def finish
|
|
81
|
+
backup_cmd "rm -rf #{@tempdir}" if File.exists?(@tempdir)
|
|
82
|
+
backup_cmd "rm #{@tarball}" if File.exists?(@tarball)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
def backup_cmd(command)
|
|
88
|
+
system command
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def service(filename, &block)
|
|
93
|
+
if Backup.behavior == :restore
|
|
94
|
+
restore filename, &block
|
|
95
|
+
else
|
|
96
|
+
backup filename, &block
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def backup(filename, &block)
|
|
101
|
+
BackupScript.backup filename, &block
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def restore(filename, &block)
|
|
105
|
+
BackupScript.restore filename, &block
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require 'yaml'
|
|
2
|
+
|
|
3
|
+
module Shnell
|
|
4
|
+
module Config
|
|
5
|
+
def db_user
|
|
6
|
+
read_config(:db, :user)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def db_password
|
|
10
|
+
read_config(:db, :password)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def db_credentials
|
|
14
|
+
"-u#{db_user} #{"-p#{db_password}" if db_password != ''}"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def ftp_host
|
|
18
|
+
read_config(:ftp, :host)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def ftp_user
|
|
22
|
+
read_config(:ftp, :user)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def ftp_password
|
|
26
|
+
read_config(:ftp, :password)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def read_config(scope, key)
|
|
30
|
+
hash = config[scope.to_s] || {}
|
|
31
|
+
value = hash[key.to_s]
|
|
32
|
+
if value.nil?
|
|
33
|
+
question = "Give me the #{scope} #{key}:"
|
|
34
|
+
value = if key.to_s =~ /password/
|
|
35
|
+
ask(question) { |q| q.echo = "*" }
|
|
36
|
+
else
|
|
37
|
+
ask(question)
|
|
38
|
+
end
|
|
39
|
+
write_config scope, key, value
|
|
40
|
+
end
|
|
41
|
+
value
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def write_config(scope, key, value)
|
|
45
|
+
hash = config
|
|
46
|
+
hash[scope.to_s] ||= {}
|
|
47
|
+
hash[scope.to_s].update key.to_s => value
|
|
48
|
+
File.open(CONFIG_FILENAME, "w") do |file|
|
|
49
|
+
file << YAML.dump(hash)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def config
|
|
54
|
+
content = File.read(CONFIG_FILENAME) rescue nil
|
|
55
|
+
return {} unless content
|
|
56
|
+
YAML.load(content)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
metadata
CHANGED
|
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
|
4
4
|
prerelease: false
|
|
5
5
|
segments:
|
|
6
6
|
- 0
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
version: 0.
|
|
7
|
+
- 3
|
|
8
|
+
- 0
|
|
9
|
+
version: 0.3.0
|
|
10
10
|
platform: ruby
|
|
11
11
|
authors:
|
|
12
12
|
- Johannes J. Schmidt
|
|
@@ -57,8 +57,11 @@ extra_rdoc_files:
|
|
|
57
57
|
files:
|
|
58
58
|
- VERSION
|
|
59
59
|
- bin/shnell
|
|
60
|
-
- lib/backup.rb
|
|
61
60
|
- lib/shnell.rb
|
|
61
|
+
- lib/shnell/actions/database.rb
|
|
62
|
+
- lib/shnell/actions/ftp.rb
|
|
63
|
+
- lib/shnell/backup.rb
|
|
64
|
+
- lib/shnell/config.rb
|
|
62
65
|
- LICENSE
|
|
63
66
|
- README.rdoc
|
|
64
67
|
has_rdoc: true
|
data/lib/backup.rb
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
require 'net/ftp'
|
|
2
|
-
require 'yaml'
|
|
3
|
-
|
|
4
|
-
module Backup
|
|
5
|
-
include Filander
|
|
6
|
-
|
|
7
|
-
class << self
|
|
8
|
-
attr_accessor :behavior
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
class BackupScript
|
|
12
|
-
class << self
|
|
13
|
-
def backup(name, &block)
|
|
14
|
-
backup = self.new(name)
|
|
15
|
-
backup.prepare
|
|
16
|
-
backup.instance_eval(&block)
|
|
17
|
-
backup.backup!
|
|
18
|
-
backup.finish
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def restore(name, &block)
|
|
22
|
-
backup = self.new(name)
|
|
23
|
-
backup.instance_eval(&block)
|
|
24
|
-
backup.restore!
|
|
25
|
-
backup.finish
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def initialize(service)
|
|
30
|
-
@service_root = service
|
|
31
|
-
@service_name = File.basename(service)
|
|
32
|
-
@database = @service_name.gsub(/[-\.]/, '_')
|
|
33
|
-
@tempdir = File.join("/tmp", @service_name)
|
|
34
|
-
@tarball = "#{@tempdir}.tar.bz2"
|
|
35
|
-
@directories = []
|
|
36
|
-
@databases = []
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def prepare
|
|
40
|
-
backup_cmd "mkdir -p #{@tempdir}"
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def directory(filename)
|
|
44
|
-
report :directory, filename
|
|
45
|
-
@directories << filename
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def database(database = @database)
|
|
49
|
-
report :database, database
|
|
50
|
-
@databases << database
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def backup!
|
|
54
|
-
@directories.each do |filename|
|
|
55
|
-
filename = File.join(@service_root, filename)
|
|
56
|
-
backup_cmd "cp -r #{filename} #{@tempdir}/"
|
|
57
|
-
end
|
|
58
|
-
@databases.each do |database|
|
|
59
|
-
backup_cmd "mysqldump -u#{db_user} #{"-p#{db_password}" if db_password != ''} #{database} > #{File.join(@tempdir, "#{database}.sql")}"
|
|
60
|
-
end
|
|
61
|
-
backup_cmd "tar -C /tmp -cjf #{@tarball} #{@service_name}"
|
|
62
|
-
Net::FTP.open(ftp_host) do |ftp|
|
|
63
|
-
ftp.login ftp_user, ftp_password
|
|
64
|
-
ftp.putbinaryfile @tarball
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def restore!
|
|
69
|
-
inside "/tmp" do
|
|
70
|
-
Net::FTP.open(ftp_host) do |ftp|
|
|
71
|
-
ftp.login ftp_user, ftp_password
|
|
72
|
-
ftp.getbinaryfile File.basename(@tarball)
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
backup_cmd "tar -C /tmp -xf #{@tarball}"
|
|
76
|
-
@databases.each do |database|
|
|
77
|
-
backup_cmd "mysql -u#{db_user} #{"-p#{db_password}" if db_password != ''} #{database} < #{File.join(@tempdir, "#{database}.sql")}"
|
|
78
|
-
end
|
|
79
|
-
@directories.each do |filename|
|
|
80
|
-
source = File.join(@tempdir, filename)
|
|
81
|
-
dest = File.join(@service_root, filename)
|
|
82
|
-
backup_cmd "cp -r #{source} #{dest}"
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def finish
|
|
87
|
-
backup_cmd "rm -rf #{@tempdir}"
|
|
88
|
-
backup_cmd "rm #{@tarball}"
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
private
|
|
92
|
-
|
|
93
|
-
def backup_cmd(command)
|
|
94
|
-
system command
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
def db_user
|
|
98
|
-
read_config(:db, :user)
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def db_password
|
|
102
|
-
read_config(:db, :password)
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def ftp_host
|
|
106
|
-
read_config(:ftp, :host)
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
def ftp_user
|
|
110
|
-
read_config(:ftp, :user)
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def ftp_password
|
|
114
|
-
read_config(:ftp, :password)
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def read_config(scope, key)
|
|
118
|
-
hash = config[scope.to_s] || {}
|
|
119
|
-
value = hash[key.to_s]
|
|
120
|
-
if value.nil?
|
|
121
|
-
question = "Give me the #{scope} #{key}:"
|
|
122
|
-
value = if key.to_s =~ /password/
|
|
123
|
-
ask(question) { |q| q.echo = "*" }
|
|
124
|
-
else
|
|
125
|
-
ask(question)
|
|
126
|
-
end
|
|
127
|
-
write_config scope, key, value
|
|
128
|
-
end
|
|
129
|
-
value
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
def write_config(scope, key, value)
|
|
133
|
-
hash = config
|
|
134
|
-
hash[scope.to_s] ||= {}
|
|
135
|
-
hash[scope.to_s].update key.to_s => value
|
|
136
|
-
File.open(CONFIG_FILENAME, "w") do |file|
|
|
137
|
-
file << YAML.dump(hash)
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
def config
|
|
142
|
-
content = File.read(CONFIG_FILENAME) rescue nil
|
|
143
|
-
return {} unless content
|
|
144
|
-
YAML.load(content)
|
|
145
|
-
end
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
def service(filename, &block)
|
|
149
|
-
if Backup.behavior == :restore
|
|
150
|
-
restore filename, &block
|
|
151
|
-
else
|
|
152
|
-
backup filename, &block
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
def backup(filename, &block)
|
|
157
|
-
BackupScript.backup filename, &block
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
def restore(filename, &block)
|
|
161
|
-
BackupScript.restore filename, &block
|
|
162
|
-
end
|
|
163
|
-
end
|