cknife 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +81 -4
- data/VERSION +1 -1
- data/bin/cknifemysql +5 -0
- data/cknife.gemspec +7 -4
- data/lib/cknife/cknife_mysql.rb +83 -0
- data/lib/cknife/command_line.rb +62 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 10d313111e83364d913d12d981ccbca713a6d36e
|
4
|
+
data.tar.gz: def05bdb2b133e4d94660097a0b7a9661be2102c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01a7497e314bcefcdd892afa20fefcf320f48713b561c9ff856e52d983b00c109fe8a40eff9e72d2a3bcc3e625dd10bab95ed9dd6cf91cf059b583a23b2c19d7
|
7
|
+
data.tar.gz: ba94d943c666da16b953e8f2db2614d7f9670fcdb40166d314e127761f17d018b65d10707a696f73ea6c0c1bc26cf1547ec6d3ca9c9b8507e9ce3d11af592ad5
|
data/README.md
CHANGED
@@ -194,9 +194,13 @@ switched to DNS Simple and don't use this much anymore.
|
|
194
194
|
cknifezerigo help [TASK] # Describe available tasks or one specific task
|
195
195
|
cknifezerigo list # List available host names.
|
196
196
|
|
197
|
-
#
|
197
|
+
# PostgreSQL Backups
|
198
198
|
|
199
|
-
This
|
199
|
+
This is a wrapper around the PostgreSQL backup and restore command
|
200
|
+
line utilities.
|
201
|
+
|
202
|
+
It requires the following Rails-style configuration in the
|
203
|
+
configuration file:
|
200
204
|
|
201
205
|
pg:
|
202
206
|
host: localhost
|
@@ -204,8 +208,8 @@ This requires the following setup in the configuration:
|
|
204
208
|
username: dbuser
|
205
209
|
password: dbpassword
|
206
210
|
|
207
|
-
|
208
|
-
|
211
|
+
Then you can capture a snapshot of your database. You can also restore
|
212
|
+
it using this tool.
|
209
213
|
|
210
214
|
> bundle exec cknifepg help
|
211
215
|
Tasks:
|
@@ -215,6 +219,51 @@ cknife config file) and you can capture a snapshot of your database.
|
|
215
219
|
cknifepg restore # Restore a file. Use the one with the most recent mtime by default. Searches for db*.dump files in the CWD.
|
216
220
|
cknifepg sessions # List active sessions in this database and provide a string suitable for giving to kill for stopping those sessions.
|
217
221
|
|
222
|
+
This generates and deletes a `.pgpass` file before and after the
|
223
|
+
command line session. Be aware that if this process is interrupted,
|
224
|
+
the `.pgpass` file may be left on disk in the CWD.
|
225
|
+
|
226
|
+
# MySQL Backups
|
227
|
+
|
228
|
+
Like pg, this requires a similar setup in the configuration:
|
229
|
+
|
230
|
+
mysql:
|
231
|
+
host: localhost
|
232
|
+
database: dbname
|
233
|
+
username: dbuser
|
234
|
+
password: dbpassword
|
235
|
+
|
236
|
+
Then you can capture a snapshot of your database.
|
237
|
+
|
238
|
+
> bundle exec cknifemysql help
|
239
|
+
Tasks:
|
240
|
+
cknifemysql capture # Capture a dump of the database to db(current timestamp).sql.
|
241
|
+
cknifemysql help [TASK] # Describe available tasks or one specific task
|
242
|
+
cknifemysql restore # Restore a file. Use the one with the most recent mtime by default. Searches for db*.sql files in the CWD.
|
243
|
+
|
244
|
+
Sample output:
|
245
|
+
|
246
|
+
> bundle exec cknifemysql capture
|
247
|
+
mysqldump --defaults-file=my.cnf -h localhost -P 3306 -u dbuser dbname --add-drop-database --result-file=db20150617125335.sql
|
248
|
+
Captured db20150617125335.sql.
|
249
|
+
|
250
|
+
And the accompanying restore, were you to run it immediately afterwards:
|
251
|
+
|
252
|
+
> bundle exec cknifemysql restore
|
253
|
+
Restore db20150617125335.sql? y
|
254
|
+
Doing restore...
|
255
|
+
mysql --defaults-file=my.cnf -h localhost -P 3306 -u dbuser dbname
|
256
|
+
source db20150617125335.sql;
|
257
|
+
Restored db20150617125335.sql
|
258
|
+
|
259
|
+
**Important:** As you can see, a my.cnf is generated and your password
|
260
|
+
stored in there. That file is removed when the command is done
|
261
|
+
executing. This keeps your password off of the command line and
|
262
|
+
hidden from certain `top` or `ps` invocations by other users who may
|
263
|
+
be on the same machine. This rational is taken from the PostgreSQL
|
264
|
+
PGPASSFILE documentation. If this command error's-out, you'll be
|
265
|
+
warned to remove this file yourself for security purposes.
|
266
|
+
|
218
267
|
# Dub
|
219
268
|
|
220
269
|
Like du, but sorts your output by size. This helps you determine
|
@@ -231,6 +280,34 @@ Options:
|
|
231
280
|
|
232
281
|
-c Enable colorized output.
|
233
282
|
|
283
|
+
# A typical cron script for capturing PostgreSQL backups and uploading them to S3
|
284
|
+
|
285
|
+
#!/bin/bash
|
286
|
+
|
287
|
+
source "$HOME/.rvm/scripts/rvm";
|
288
|
+
|
289
|
+
rvm use 2.0.0;
|
290
|
+
|
291
|
+
cd path/to/backups/dir/with/cknife/config;
|
292
|
+
|
293
|
+
cknifepg capture;
|
294
|
+
|
295
|
+
cknifeaws upsync backups-bucket . --noprompt --backups-retain --glob="db*.dump";
|
296
|
+
|
297
|
+
Which can be used with the following sample [crontab](http://en.wikipedia.org/wiki/Cron#Examples),
|
298
|
+
executing once a day at 2am:
|
299
|
+
|
300
|
+
# * * * * * command to execute
|
301
|
+
# │ │ │ │ │
|
302
|
+
# │ │ │ │ │
|
303
|
+
# │ │ │ │ └───── day of week (0 - 6) (0 to 6 are Sunday to Saturday, or use names; 7 is Sunday, the same as 0)
|
304
|
+
# │ │ │ └────────── month (1 - 12)
|
305
|
+
# │ │ └─────────────── day of month (1 - 31)
|
306
|
+
# │ └──────────────────── hour (0 - 23)
|
307
|
+
# └───────────────────────── min (0 - 59)
|
308
|
+
|
309
|
+
0 2 * * * path/to/script > /dev/null
|
310
|
+
|
234
311
|
|
235
312
|
# Contributing
|
236
313
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.7
|
data/bin/cknifemysql
ADDED
data/cknife.gemspec
CHANGED
@@ -2,19 +2,19 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: cknife 0.1.
|
5
|
+
# stub: cknife 0.1.7 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "cknife"
|
9
|
-
s.version = "0.1.
|
9
|
+
s.version = "0.1.7"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Mike De La Loza"]
|
14
|
-
s.date = "2015-06-
|
14
|
+
s.date = "2015-06-17"
|
15
15
|
s.description = "Cali Army Knife, a collection of command line tools, especially for popular API services."
|
16
16
|
s.email = "mikedll@mikedll.com"
|
17
|
-
s.executables = ["cknifeaws", "cknifedub", "cknifemail", "cknifenowtimestamp", "cknifepg", "cknifewcdir", "cknifezerigo"]
|
17
|
+
s.executables = ["cknifeaws", "cknifedub", "cknifemail", "cknifemysql", "cknifenowtimestamp", "cknifepg", "cknifewcdir", "cknifezerigo"]
|
18
18
|
s.extra_rdoc_files = [
|
19
19
|
"LICENSE",
|
20
20
|
"README.md"
|
@@ -31,13 +31,16 @@ Gem::Specification.new do |s|
|
|
31
31
|
"bin/cknifeaws",
|
32
32
|
"bin/cknifedub",
|
33
33
|
"bin/cknifemail",
|
34
|
+
"bin/cknifemysql",
|
34
35
|
"bin/cknifenowtimestamp",
|
35
36
|
"bin/cknifepg",
|
36
37
|
"bin/cknifewcdir",
|
37
38
|
"bin/cknifezerigo",
|
38
39
|
"cknife.gemspec",
|
39
40
|
"cknife.yml.sample",
|
41
|
+
"lib/cknife/cknife_mysql.rb",
|
40
42
|
"lib/cknife/cknife_pg.rb",
|
43
|
+
"lib/cknife/command_line.rb",
|
41
44
|
"lib/cknife/config.rb"
|
42
45
|
]
|
43
46
|
s.homepage = "http://github.com/mikedll/cali-army-knife"
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'open3'
|
2
|
+
require 'thor'
|
3
|
+
require 'cknife/config'
|
4
|
+
require 'cknife/command_line'
|
5
|
+
|
6
|
+
module CKnife
|
7
|
+
class CKnifeMysql < Thor
|
8
|
+
|
9
|
+
no_tasks do
|
10
|
+
def config
|
11
|
+
@config ||= Config
|
12
|
+
end
|
13
|
+
|
14
|
+
def conf
|
15
|
+
@conf ||= {
|
16
|
+
:host => config['mysql.host'] || "localhost",
|
17
|
+
:port => config['mysql.port'] || 3306,
|
18
|
+
:database => config['mysql.database'],
|
19
|
+
:username => config['mysql.username'],
|
20
|
+
:password => config['mysql.password']
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def connection_options
|
25
|
+
"--defaults-file=#{option_file} -h #{conf[:host]} -P #{conf[:port]} -u #{conf[:username]}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def option_file
|
29
|
+
@option_file ||= "my.cnf"
|
30
|
+
end
|
31
|
+
|
32
|
+
def command_line
|
33
|
+
@command_line ||= CommandLine.new(option_file, "[client]\npassword=\"#{conf[:password]}\"", self)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "capture", "Capture a dump of the database to db(current timestamp).sql."
|
39
|
+
def capture
|
40
|
+
file_name = "db" + Time.now.strftime("%Y%m%d%H%M%S") + ".sql"
|
41
|
+
|
42
|
+
if File.exists?(file_name)
|
43
|
+
say("File already exists: #{file_name}.", :red)
|
44
|
+
end
|
45
|
+
|
46
|
+
command_line.with_option_file do |c|
|
47
|
+
c.execute "mysqldump #{connection_options} #{conf[:database]} --add-drop-database --result-file=#{file_name}" do
|
48
|
+
say("Captured #{file_name}.")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
desc "restore", "Restore a file. Use the one with the most recent mtime by default. Searches for db*.sql files in the CWD."
|
54
|
+
method_options :filename => nil
|
55
|
+
def restore
|
56
|
+
to_restore = options[:filename] if options[:filename]
|
57
|
+
if to_restore.nil?
|
58
|
+
files = Dir["db*.sql"]
|
59
|
+
with_mtime = files.map { |f| [f, File.mtime(f)] }
|
60
|
+
with_mtime.sort! { |a,b| a.last <=> b.last }
|
61
|
+
files = with_mtime.map(&:first)
|
62
|
+
to_restore = files.last
|
63
|
+
end
|
64
|
+
|
65
|
+
if to_restore.nil?
|
66
|
+
say("No backups file to restore. None given on the command line and none could be found in the CWD.", :red)
|
67
|
+
return
|
68
|
+
else
|
69
|
+
if !yes?("Restore #{to_restore}?", :green)
|
70
|
+
return
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
command_line.with_option_file do |c|
|
75
|
+
say("Doing restore...")
|
76
|
+
|
77
|
+
c.execute("mysql #{connection_options} #{conf[:database]}", "source #{to_restore};") do
|
78
|
+
say("Restored #{to_restore}")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module CKnife
|
2
|
+
class CommandLine
|
3
|
+
|
4
|
+
attr_accessor :option_file, :option_file_contents, :thor_output
|
5
|
+
|
6
|
+
def initialize(f, s, o)
|
7
|
+
self.option_file = f
|
8
|
+
self.option_file_contents = s
|
9
|
+
self.thor_output = o
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute(cmd, input = nil)
|
13
|
+
return if !@session_ok
|
14
|
+
puts cmd
|
15
|
+
stdin, stdout, stderr, wait_thread = Open3.popen3(cmd)
|
16
|
+
if input
|
17
|
+
puts input
|
18
|
+
stdin.write input
|
19
|
+
stdin.close
|
20
|
+
end
|
21
|
+
output = stdout.read
|
22
|
+
output += stderr.read
|
23
|
+
$stdout.write output
|
24
|
+
stdout.close
|
25
|
+
stderr.close
|
26
|
+
result = wait_thread.value.to_i
|
27
|
+
@session_ok = @session_ok && (result == 0)
|
28
|
+
yield if @session_ok && block_given?
|
29
|
+
output
|
30
|
+
end
|
31
|
+
|
32
|
+
def with_option_file
|
33
|
+
if @session_live
|
34
|
+
return yield
|
35
|
+
end
|
36
|
+
|
37
|
+
@session_live = true
|
38
|
+
@session_ok = true
|
39
|
+
|
40
|
+
if File.exists?(option_file)
|
41
|
+
thor_output.say("This generates a file named #{option_file}, but one is already on disk. Exiting.")
|
42
|
+
return
|
43
|
+
end
|
44
|
+
|
45
|
+
File.open(option_file, "w", 0600) { |f| f.write option_file_contents }
|
46
|
+
|
47
|
+
result = yield self
|
48
|
+
|
49
|
+
FileUtils.rm(option_file)
|
50
|
+
if File.exists?(option_file)
|
51
|
+
thor_output.say("Failed to remove #{option_file} file. Please remove it for security purposes.")
|
52
|
+
end
|
53
|
+
|
54
|
+
thor_output.say
|
55
|
+
thor_output.say("Command failed.", :red) if !@session_ok
|
56
|
+
@session_live = false
|
57
|
+
|
58
|
+
result
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cknife
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike De La Loza
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-06-
|
11
|
+
date: 2015-06-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rest-client
|
@@ -215,6 +215,7 @@ executables:
|
|
215
215
|
- cknifeaws
|
216
216
|
- cknifedub
|
217
217
|
- cknifemail
|
218
|
+
- cknifemysql
|
218
219
|
- cknifenowtimestamp
|
219
220
|
- cknifepg
|
220
221
|
- cknifewcdir
|
@@ -235,13 +236,16 @@ files:
|
|
235
236
|
- bin/cknifeaws
|
236
237
|
- bin/cknifedub
|
237
238
|
- bin/cknifemail
|
239
|
+
- bin/cknifemysql
|
238
240
|
- bin/cknifenowtimestamp
|
239
241
|
- bin/cknifepg
|
240
242
|
- bin/cknifewcdir
|
241
243
|
- bin/cknifezerigo
|
242
244
|
- cknife.gemspec
|
243
245
|
- cknife.yml.sample
|
246
|
+
- lib/cknife/cknife_mysql.rb
|
244
247
|
- lib/cknife/cknife_pg.rb
|
248
|
+
- lib/cknife/command_line.rb
|
245
249
|
- lib/cknife/config.rb
|
246
250
|
homepage: http://github.com/mikedll/cali-army-knife
|
247
251
|
licenses:
|