redis-backup 0.0.2 → 0.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/Gemfile CHANGED
@@ -1,6 +1,3 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in svn-backup.gemspec
4
3
  gemspec
5
- gem 'aws-sdk'
6
- gem 'redis'
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  redis-backup
2
2
  ============
3
3
 
4
- a small ruby gem that allows automated redis-backups
4
+ a small ruby gem that allows automated redis RDB-file backups with support for compression and S3 uploading.
5
5
 
6
6
  Installation
7
7
  ============
@@ -12,15 +12,21 @@ Usage
12
12
  =====
13
13
 
14
14
  redis-backup [options]
15
- -h, --help Usage information
16
- -b, --backup-dir BACKUP_DIR Directory to write backups to
17
- -s, --redis-source REDIS_SOURCE Full path to redis dump.rdb file
18
- -m REDIS_SAVE_METHOD, The method to call on redis for saving (save or bgsave or none)
19
- --redis-save-method
20
- -H, --redis-host REDIS_HOST Host for local redis
21
- -p, --redis-port REDIS_PORT Port for local redis
22
- -B, --s3-bucket S3_BUCKET Name of bucket to use on S3
23
- -A S3_ACCESS_KEY_ID, Your access_key_id for AWS S3
24
- --s3-access-key-id
25
- -S S3_SECRET_ACCESS_KEY, Your secret_access_key for AWS S3
26
- --s3-secret-access-key
15
+ Specific options:
16
+ -b, --backup-dir BACKUP_DIR Directory to write backups to
17
+ -c, --compress Compress backup as a zip file
18
+ -s, --redis-source REDIS_SOURCE Full path to redis dump.rdb file
19
+ -m REDIS_SAVE_METHOD, The method to call on redis for saving (save or bgsave or none)
20
+ --redis-save-method
21
+ -H, --redis-host REDIS_HOST Host for local redis
22
+ -p, --redis-port REDIS_PORT Port for local redis
23
+ -A S3_ACCESS_KEY_ID, Your access_key_id for AWS S3
24
+ --s3-access-key-id
25
+ -B, --s3-bucket S3_BUCKET Name of bucket to use on S3
26
+ -C, --s3-clean Cleanup intermediate backup files
27
+ -S S3_SECRET_ACCESS_KEY, Your secret_access_key for AWS S3
28
+ --s3-secret-access-key
29
+
30
+ Common options:
31
+ -h, --help Show this message
32
+ --version Show version
@@ -3,125 +3,63 @@
3
3
 
4
4
  #
5
5
  # redis-backup
6
- #
7
- # Uses environment variables for running:
8
- #
9
- # - BACKUP_DIR: Directory to write backups to
10
- # - REDIS_SAVE: 0 or 1. If "1", then perform, and wait for, a bgsave before copying backup
11
- # - REDIS_SAVE_METHOD: If calling a save, the method to call on redis for saving (save or bgsave)
12
- # - REDIS_HOST: Host for local redis
13
- # - REDIS_PORT: Port to local redis
14
- # - REDIS_SOURCE: Full path to redis dump.rdb file
15
- # - S3_SAVE: 0 or 1. If "1", then use S3 to backup the file
16
- # - S3_BUCKET: Name of bucket to use on S3
17
- # - S3_ACCESS_KEY_ID: Your access_key_id for AWS S3
18
- # - S3_SECRET_ACCESS_KEY: Your secret_access_key for AWS S3
19
- #
20
6
 
21
7
  require 'aws-sdk'
22
8
  require 'date'
23
9
  require 'fileutils'
24
- require 'optparse'
25
10
  require 'redis'
11
+ require 'zip/zip'
26
12
 
27
- require File.expand_path('../../lib/redis-backup/version', __FILE__)
28
- version = RedisBackup::VERSION
29
-
30
- backup_dir = "/data/backup/redis"
31
- redis_host = "localhost"
32
- redis_port = 6379
33
- redis_save_method = false
34
- redis_source = "/var/lib/redis/dump.rdb"
35
- s3_save = !!ENV.fetch("S3_SAVE", false)
36
- s3_bucket = false
37
- s3_access_key_id = false
38
- s3_secret_access_key = false
39
-
40
- optparse = OptionParser.new do |opts|
41
- opts.version = version
42
- opts.banner = "Usage: redis-backup [options]"
43
- opts.on('-h', '--help', 'Usage information') do
44
- puts opts
45
- exit
46
- end
47
- opts.on('-b', '--backup-dir BACKUP_DIR', 'Directory to write backups to') { |dir| backup_dir = dir }
48
- opts.on('-s', '--redis-source REDIS_SOURCE', 'Full path to redis dump.rdb file') { |source| redis_source = source }
49
- opts.on('-m', '--redis-save-method REDIS_SAVE_METHOD', 'The method to call on redis for saving (save or bgsave or none)') { |method| redis_save_method = method }
50
- opts.on('-H', '--redis-host REDIS_HOST', 'Host for local redis') { |host| redis_host = host }
51
- opts.on('-p', '--redis-port REDIS_PORT', 'Port for local redis') { |port| redis_port = port.to_i }
52
- opts.on('-B', '--s3-bucket S3_BUCKET', 'Name of bucket to use on S3') { |bucket| s3_bucket = bucket }
53
- opts.on('-A', '--s3-access-key-id S3_ACCESS_KEY_ID', 'Your access_key_id for AWS S3') { |key| s3_access_key_id = key }
54
- opts.on('-S', '--s3-secret-access-key S3_SECRET_ACCESS_KEY', 'Your secret_access_key for AWS S3') { |secret| s3_secret_access_key = secret }
55
- end
56
- optparse.parse!
57
-
58
- BACKUP_DIR = backup_dir
59
- REDIS_SAVE_METHOD = redis_save_method
60
- REDIS_HOST = redis_host
61
- REDIS_SOURCE = redis_source
62
- REDIS_PORT = redis_port
63
- S3_SAVE = !!s3_bucket && !!s3_access_key_id && !!s3_secret_access_key
64
- S3_BUCKET = s3_bucket
65
- S3_ACCESS_KEY_ID = s3_access_key_id
66
- S3_SECRET_ACCESS_KEY = s3_secret_access_key
67
-
68
-
69
- def colorize(text, color_code); RUBY_PLATFORM =~ /win32/ ? text : "#{color_code}#{text}\e[0m"; end
70
- def red(text); colorize(text, "\e[31m"); end
71
- def green(text); colorize(text, "\e[32m"); end
72
- def yellow(text); colorize(text, "\e[33m"); end
73
- def blue(text); colorize(text, "\e[34m"); end
74
- def magenta(text); colorize(text, "\e[35m"); end
75
- def cyan(text); colorize(text, "\e[36m"); end
76
- def white(text); colorize(text, "\e[37m"); end
77
- def bold(text); colorize(text, "\e[1m"); end
78
- def grey(text); colorize(text, "\e[90m"); end
79
-
80
- abort("Redis .rdb file does not exist: " + REDIS_SOURCE) unless File.exists? REDIS_SOURCE
81
-
82
- FileUtils.mkdir_p BACKUP_DIR unless File.directory? BACKUP_DIR
83
-
84
- abort("Backup directory does not exist: " + BACKUP_DIR) unless File.directory? BACKUP_DIR
85
- abort("Backup directory is not writable: " + BACKUP_DIR) unless File.writable? BACKUP_DIR
86
-
87
- if S3_SAVE
88
- abort("No bucket specified") unless S3_BUCKET
89
- abort("No access key specified in S3_ACCESS_KEY_ID environment variable") unless S3_ACCESS_KEY_ID
90
- abort("No secret access key specified in S3_SECRET_ACCESS_KEY environment variable") unless S3_SECRET_ACCESS_KEY
13
+ require File.expand_path('../../lib/redis-backup/options', __FILE__)
14
+ require File.expand_path('../../lib/redis-backup/utils', __FILE__)
15
+
16
+ options = RedisBackup::Options.parse(ARGV)
17
+
18
+ abort("Redis .rdb file does not exist: " + options.redis_source) unless File.exists? options.redis_source
19
+
20
+ FileUtils.mkdir_p options.backup_dir unless File.directory? options.backup_dir
21
+
22
+ abort("Backup directory does not exist: " + options.backup_dir) unless File.directory? options.backup_dir
23
+ abort("Backup directory is not writable: " + options.backup_dir) unless File.writable? options.backup_dir
24
+
25
+ if options.s3_save
26
+ abort("No bucket specified") unless options.s3_bucket
27
+ abort("No access key specified in S3_ACCESS_KEY_ID environment variable") unless options.s3_access_key_id
28
+ abort("No secret access key specified in S3_SECRET_ACCESS_KEY environment variable") unless options.s3_secret_access_key
91
29
  AWS.config({
92
- access_key_id: S3_ACCESS_KEY_ID,
93
- secret_access_key: S3_SECRET_ACCESS_KEY
30
+ access_key_id: options.s3_access_key_id,
31
+ secret_access_key: options.s3_secret_access_key
94
32
  })
95
33
  s3 = AWS::S3.new
96
- bucket = s3.buckets[S3_BUCKET]
97
- abort("Bucket does not exist: " + S3_BUCKET) unless bucket.exists?
34
+ bucket = s3.buckets[options.s3_bucket]
35
+ abort("Bucket does not exist: " + options.s3_bucket) unless bucket.exists?
98
36
  begin
99
37
  owner = bucket.owner
100
38
  rescue AWS::S3::Errors::AccessDenied => e
101
- abort("Access to the bucket is denied: " + S3_BUCKET)
39
+ abort("Access to the bucket is denied: " + options.s3_bucket)
102
40
  end
103
41
  end
104
42
 
105
43
 
106
- puts blue(cyan('Starting save'))
44
+ puts RedisBackup::Utils.cyan('Starting save')
107
45
  backup_start = Time.now
108
46
 
109
- puts "--> Saving from %s to %s" % [ REDIS_SOURCE, BACKUP_DIR ]
47
+ puts "--> Saving from %s to %s" % [ options.redis_source, options.backup_dir ]
110
48
 
111
- if REDIS_SAVE_METHOD
112
- puts "--> Performing background save " + bold(cyan('↴'))
49
+ if options.redis_save_method
50
+ puts "--> Performing background save " + RedisBackup::Utils.bold(RedisBackup::Utils.cyan('↴'))
113
51
  bgsave_start = Time.now
114
52
 
115
- mtime = File.mtime(REDIS_SOURCE).strftime("%Y-%m-%d-%H-%M-%S")
53
+ mtime = File.mtime(options.redis_source).strftime("%Y-%m-%d-%H-%M-%S")
116
54
  puts " - Current backup.rdb mtime: " + mtime
117
55
 
118
- puts " - Sending '%s' command" % (REDIS_SAVE_METHOD)
56
+ puts " - Sending '%s' command" % (options.redis_save_method)
119
57
  redis = Redis.new(
120
- :host => REDIS_HOST,
121
- :port => REDIS_PORT
58
+ :host => options.redis_host,
59
+ :port => options.redis_port
122
60
  )
123
61
 
124
- if REDIS_SAVE_METHOD == "bgsave"
62
+ if options.redis_save_method == "bgsave"
125
63
  redis.bgsave
126
64
  else
127
65
  redis.save
@@ -129,36 +67,66 @@ if REDIS_SAVE_METHOD
129
67
 
130
68
  puts " - Command sent, waiting"
131
69
 
132
- while File.mtime(REDIS_SOURCE).strftime("%Y-%m-%d-%H-%M-%S") == mtime
70
+ while File.mtime(options.redis_source).strftime("%Y-%m-%d-%H-%M-%S") == mtime
133
71
  sleep 0.0001
134
72
  end
135
73
 
136
- puts " - Save performed successfully, took %.2f seconds" % (Time.now - backup_start)
74
+ puts " - Save performed successfully, took %.2f seconds" % (Time.now - bgsave_start)
137
75
  end
138
76
 
139
- DATETIME = DateTime.parse(`date`).strftime("%Y-%m-%d-%H-%M-%S")
140
- REDIS_DEST = "%s/%s-dump.rdb" % [ BACKUP_DIR, DATETIME ]
77
+ backup_filename = "%s-dump.rdb" % [ DateTime.parse(`date`).strftime("%Y-%m-%d-%H-%M-%S") ]
78
+ backup_rdb_file = "%s/%s" % [ options.backup_dir, backup_filename ]
79
+ backup_file = backup_rdb_file
80
+
81
+ puts "--> Copying backup from %s to %s" % [ options.redis_source, backup_rdb_file ]
82
+ copy_start = Time.now
83
+ FileUtils.cp(options.redis_source, backup_rdb_file)
84
+ puts " - Copying completed, took %.2f" % (Time.now - copy_start)
85
+ puts " - RDB filesize is %s" % (RedisBackup::Utils.filesize(backup_rdb_file))
141
86
 
142
- puts "--> Copying backup from %s to %s" % [ REDIS_SOURCE, REDIS_DEST ]
143
- FileUtils.cp(REDIS_SOURCE, REDIS_DEST)
87
+ if options.compress
88
+ puts "--> Performing compression " + RedisBackup::Utils.bold(RedisBackup::Utils.cyan('↴'))
89
+ compress_start = Time.now
144
90
 
145
- if S3_SAVE
146
- puts "--> Pushing file to S3 " + bold(cyan('↴'))
91
+ puts " - Compressing to %s.zip" % [ backup_rdb_file ]
92
+
93
+ Zip::ZipFile.open(backup_rdb_file + ".zip", Zip::ZipFile::CREATE) do |zipfile|
94
+ zipfile.add(backup_filename, backup_rdb_file)
95
+ end
96
+
97
+ if options.clean
98
+ puts " - Removing temporary rdb file"
99
+ File.delete(backup_rdb_file)
100
+ end
101
+
102
+ puts " - Compression performed successfully, took %.2f seconds" % (Time.now - compress_start)
103
+
104
+ backup_file = backup_rdb_file + ".zip"
105
+ puts " - Compression filesize is %s" % (RedisBackup::Utils.filesize(backup_file))
106
+ end
107
+
108
+ if options.s3_save
109
+ puts "--> Pushing file to S3 " + RedisBackup::Utils.bold(RedisBackup::Utils.cyan('↴'))
147
110
  s3_start = Time.now
148
111
 
149
112
  puts " - Connecting to S3"
150
113
  s3 = AWS::S3.new
151
- bucket = s3.buckets[S3_BUCKET]
114
+ bucket = s3.buckets[options.s3_bucket]
152
115
 
153
116
  puts " - Uploading the file, please wait..."
154
- basename = File.basename(REDIS_DEST)
117
+ basename = File.basename(backup_file)
155
118
  object = bucket.objects[basename]
156
- object.write(:file => REDIS_DEST)
157
- request_uri = object.url_for(:read).request_uri.gsub(S3_ACCESS_KEY_ID, "YOUR_S3_ACCESS_KEY_ID")
119
+ object.write(:file => backup_file)
120
+ request_uri = object.url_for(:read).request_uri.gsub(options.s3_access_key_id, "YOUR_S3_ACCESS_KEY_ID")
121
+
122
+ if options.clean
123
+ puts " - Removing temporary backup file"
124
+ File.delete(backup_file)
125
+ end
158
126
 
159
127
  puts " - Uploaded to: " + object.public_url.request_uri
160
- puts " - Use this URL to download the file: https://s3.amazonaws.com/" + S3_BUCKET + request_uri
128
+ puts " - Use this URL to download the file: https://s3.amazonaws.com/" + options.s3_bucket + request_uri
161
129
  puts " - S3 sync performed successfully, took %.2f seconds" % (Time.now - s3_start)
162
130
  end
163
131
 
164
- puts '🚀 ' + green('Backup took %.2f seconds' % (Time.now - backup_start))
132
+ puts '🚀 ' + RedisBackup::Utils.green('Backup took %.2f seconds' % (Time.now - backup_start))
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- encoding : utf-8 -*-
3
+
4
+ require 'optparse'
5
+ require 'ostruct'
6
+
7
+ require File.expand_path('../version', __FILE__)
8
+
9
+ module RedisBackup
10
+ class Options
11
+ def self.parse(args)
12
+ options = OpenStruct.new
13
+
14
+ options.backup_dir = "/data/backup/redis"
15
+ options.redis_host = "localhost"
16
+ options.redis_port = 6379
17
+ options.redis_save_method = false
18
+ options.redis_source = "/var/lib/redis/dump.rdb"
19
+ options.s3_save = !!ENV.fetch("S3_SAVE", false)
20
+ options.s3_bucket = false
21
+ options.s3_access_key_id = false
22
+ options.s3_secret_access_key = false
23
+
24
+ optparse = OptionParser.new do |opts|
25
+ opts.version = "redis-backup " + RedisBackup::VERSION
26
+
27
+ opts.banner = "Usage: redis-backup [options]"
28
+ opts.separator ""
29
+ opts.separator "Specific options:"
30
+
31
+ opts.on('-b', '--backup-dir BACKUP_DIR', 'Directory to write backups to') { |dir| options.backup_dir = dir }
32
+ opts.on('-c', '--compress', 'Compress backup as a zip file') { |dir| options.compress = true }
33
+ opts.on('-s', '--redis-source REDIS_SOURCE', 'Full path to redis dump.rdb file') { |source| options.redis_source = source }
34
+ opts.on('-m', '--redis-save-method REDIS_SAVE_METHOD', 'The method to call on redis for saving (save or bgsave or none)') { |method| options.redis_save_method = method }
35
+ opts.on('-H', '--redis-host REDIS_HOST', 'Host for local redis') { |host| options.redis_host = host }
36
+ opts.on('-p', '--redis-port REDIS_PORT', 'Port for local redis') { |port| options.redis_port = port.to_i }
37
+ opts.on('-A', '--s3-access-key-id S3_ACCESS_KEY_ID', 'Your access_key_id for AWS S3') { |key| options.s3_access_key_id = key }
38
+ opts.on('-B', '--s3-bucket S3_BUCKET', 'Name of bucket to use on S3') { |bucket| options.s3_bucket = bucket }
39
+ opts.on('-C', '--s3-clean', 'Cleanup intermediate backup files') { |dir| options.clean = true }
40
+ opts.on('-S', '--s3-secret-access-key S3_SECRET_ACCESS_KEY', 'Your secret_access_key for AWS S3') { |secret| options.s3_secret_access_key = secret }
41
+
42
+ opts.separator ""
43
+ opts.separator "Common options:"
44
+
45
+ opts.on_tail('-h', '--help', 'Show this message') do
46
+ puts opts
47
+ exit
48
+ end
49
+
50
+ # Another typical switch to print the version.
51
+ opts.on_tail("--version", "Show version") do
52
+ puts "redis-backup " + RedisBackup::VERSION
53
+ exit
54
+ end
55
+ end
56
+ optparse.parse!(args)
57
+
58
+ options.s3_save = !!options.s3_bucket && !!options.s3_access_key_id && !!options.s3_secret_access_key
59
+ options
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- encoding : utf-8 -*-
3
+
4
+ module RedisBackup
5
+ class Utils
6
+ def self.filesize(filename)
7
+ compressed_file_size = File.size(filename).to_f / 2**20
8
+ '%.2f MB' % compressed_file_size
9
+ end
10
+
11
+ def self.colorize(text, color_code)
12
+ RUBY_PLATFORM =~ /win32/ ? text : "#{color_code}#{text}\e[0m";
13
+ end
14
+
15
+ def self.red(text)
16
+ colorize(text, "\e[31m")
17
+ end
18
+
19
+ def self.green(text)
20
+ colorize(text, "\e[32m")
21
+ end
22
+
23
+ def self.yellow(text)
24
+ colorize(text, "\e[33m")
25
+ end
26
+
27
+ def self.blue(text)
28
+ colorize(text, "\e[34m")
29
+ end
30
+
31
+ def self.magenta(text)
32
+ colorize(text, "\e[35m")
33
+ end
34
+
35
+ def self.cyan(text)
36
+ colorize(text, "\e[36m")
37
+ end
38
+
39
+ def self.white(text)
40
+ colorize(text, "\e[37m")
41
+ end
42
+
43
+ def self.bold(text)
44
+ colorize(text, "\e[1m")
45
+ end
46
+
47
+ def self.grey(text)
48
+ colorize(text, "\e[90m")
49
+ end
50
+
51
+ end
52
+ end
@@ -1,3 +1,3 @@
1
1
  module RedisBackup
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -16,4 +16,5 @@ Gem::Specification.new do |gem|
16
16
  gem.version = RedisBackup::VERSION
17
17
  gem.add_dependency(%q<aws-sdk>, [">= 0"])
18
18
  gem.add_dependency(%q<redis>, [">= 0"])
19
+ gem.add_dependency(%q<rubyzip>, [">= 0"])
19
20
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis-backup
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-19 00:00:00.000000000 Z
12
+ date: 2013-05-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: aws-sdk
@@ -43,6 +43,22 @@ dependencies:
43
43
  - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
45
  version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rubyzip
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
46
62
  description: redis-backup is a simple backup script to automate the creation and storage
47
63
  or redis dump.rdb files.
48
64
  email:
@@ -59,6 +75,8 @@ files:
59
75
  - Rakefile
60
76
  - bin/redis-backup
61
77
  - lib/redis-backup.rb
78
+ - lib/redis-backup/options.rb
79
+ - lib/redis-backup/utils.rb
62
80
  - lib/redis-backup/version.rb
63
81
  - redis-backup.gemspec
64
82
  homepage: https://github.com/josegonzalez/redis-backup