jage-rmysqldump 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/bin/rmysqldump.rb +198 -0
  2. data/rmysqldump.conf +23 -0
  3. metadata +63 -0
@@ -0,0 +1,198 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # $Id: rmysqldump.rb,v 1.7 2007/11/28 11:48:22 jage Exp $
4
+ #
5
+ # Written by Johan Eckerstr�m <johan@jage.se>
6
+ #
7
+ # 2007-05-22 - Stop using regexp for owner_map \
8
+ # and improve syslog message
9
+ # 2006-12-19 - Compression for servers
10
+ # 2006-12-01 - External configuration file
11
+ # 2006-11-21 - Easier to change the user mapping regexp
12
+ # 2006-10-31 - Added syslog capabilities
13
+ # 2006-08-06 - First version
14
+ #
15
+ # Todo:
16
+ # - Add regexp capabilities for the database-specifications
17
+ # - Record elapsed time for backup
18
+
19
+ begin
20
+ require 'fileutils'
21
+ require 'syslog'
22
+ require 'rubygems'
23
+ require 'mysql'
24
+ rescue LoadError
25
+ $stderr.puts 'Could not load required libraries'; exit 1
26
+ end
27
+
28
+ begin
29
+ load '/etc/rmysqldump.conf'
30
+ rescue LoadError
31
+ $stderr.puts 'Could not load configuration'; exit 1
32
+ end
33
+
34
+ $users = []
35
+ IO.foreach('/etc/passwd') do |line|
36
+ $users << /(^[\w]+)/.match(line).to_s.strip
37
+ end
38
+
39
+ module MySQL
40
+ class Databases
41
+
42
+ attr_reader :list
43
+
44
+ def initialize
45
+ @list = databases.collect {|i| Database.new(i) }
46
+ end
47
+
48
+ def failed
49
+ @list.select {|i| i.fail }
50
+ end
51
+
52
+ def skipped
53
+ @list.select {|i| i.skip }
54
+ end
55
+
56
+ def successes
57
+ @list.select {|i| i.success }
58
+ end
59
+
60
+ private
61
+
62
+ def databases
63
+ list = []
64
+ connection = Mysql.real_connect($server[:host],
65
+ $server[:user],
66
+ $server[:password])
67
+ result = connection.query('SHOW DATABASES')
68
+ result.each {|db| list << db.to_s }
69
+ result.free
70
+ list
71
+ rescue Mysql::Error => error
72
+ $stderr.puts error.message; exit 1
73
+ end
74
+ end
75
+
76
+ class Database
77
+
78
+ attr_reader :name, :lock, :owner, :group, :charset, :skip
79
+ attr_accessor :success
80
+
81
+ def initialize(name)
82
+ @options = $database_options[name.to_sym] ||= Hash.new
83
+
84
+ @name = name
85
+ @lock = option_for(:lock)
86
+ @owner = option_for(:owner).to_s
87
+ @group = option_for(:group).to_s
88
+ @charset = option_for(:charset).to_s
89
+ @skip = option_for(:skip)
90
+
91
+ # Would be better if the database specific owner could override this
92
+ if option_for(:map_owner) && owner = find_owner
93
+ @owner = owner
94
+ end
95
+ end
96
+
97
+ def to_s
98
+ name
99
+ end
100
+
101
+ def path
102
+ "#{$archive_dir}/#{self}.sql.gz"
103
+ end
104
+
105
+ def fail
106
+ !success && !skip
107
+ end
108
+
109
+ private
110
+
111
+ def option_for(key)
112
+ @options[key] || $global_options[key] || false
113
+ end
114
+
115
+ def find_owner
116
+ match = $users.select do |u|
117
+ @name.include?(u) && u == @name[0...u.length]
118
+ end
119
+
120
+ if match.empty?
121
+ false
122
+ else
123
+ match.to_s
124
+ end
125
+ end
126
+ end
127
+
128
+ class Dump
129
+ def initialize(databases)
130
+ @databases = databases
131
+
132
+ unless mysqldump_working?
133
+ failure("Could not execute #{$mysqldump}"); exit 1
134
+ end
135
+
136
+ unless File.directory?($archive_dir)
137
+ failure("Could not save in #{$archive_dir}"); exit 1
138
+ end
139
+ end
140
+
141
+ def execute
142
+ Syslog.open(ident='rmysqldump', facility=Syslog::LOG_DAEMON)
143
+ @databases.list.each do |database|
144
+ unless database.skip
145
+ `#{$mysqldump} #{parameters_for(database)} #{database} | #{$gzip} > #{database.path}`
146
+ failure("Could not dump #{database}") unless $?.success?
147
+ begin
148
+ FileUtils.chown database.owner, database.group, database.path
149
+ FileUtils.chmod 0660, database.path
150
+ database.success = true if $?.success?
151
+ rescue => error
152
+ failure("Could not set permissions: #{error.message}")
153
+ end
154
+ end
155
+ end
156
+ message = "#{@databases.successes.length} databases dumped successfully"
157
+ if @databases.skipped.length > 0
158
+ message += ", #{@databases.skipped.length} skipped"
159
+ end
160
+ Syslog.info(message)
161
+
162
+ # Inform about failures
163
+ if @databases.failed.length > 0
164
+ error_message = 'Failed databases:'
165
+ @databases.failed.each do |db|
166
+ error_message << " #{db},"
167
+ end
168
+ error_message.gsub!(/,$/, '.')
169
+ Syslog.err(error_message)
170
+ end
171
+
172
+ Syslog.close
173
+ end
174
+
175
+ private
176
+
177
+ def failure(message)
178
+ $stderr.puts message
179
+ Syslog.err(message) if Syslog.opened?
180
+ end
181
+
182
+ def mysqldump_working?
183
+ File.readable?($mysqldump) and File.executable?($mysqldump)
184
+ end
185
+
186
+ def parameters_for(database)
187
+ params = "--default-character-set=#{database.charset} \
188
+ --user #{$server[:user]} \
189
+ --password=#{$server[:password]} \
190
+ --host #{$server[:host]}"
191
+ params += " --compress" if $server[:compress]
192
+ params += " --lock-tables" if database.lock
193
+ params
194
+ end
195
+ end
196
+ end
197
+
198
+ MySQL::Dump.new(MySQL::Databases.new).execute
@@ -0,0 +1,23 @@
1
+ $mysqldump = '/usr/local/bin/mysqldump'
2
+ $gzip = '/usr/bin/gzip'
3
+ $archive_dir = '/archive/mysqldump'
4
+
5
+ $server = {
6
+ :host => 'localhost',
7
+ :user => 'dumper',
8
+ :password => 'hemlis',
9
+ :compress => true # Compress the data stream
10
+ }
11
+
12
+ $database_options = {
13
+ :apachelogs => { :skip => true }
14
+ }
15
+
16
+ $global_options = {
17
+ :lock => false, # Lock the tables before dump
18
+ :owner => 'root', # Default user to own the backups
19
+ :group => 'wheel', # Default group to own the backups
20
+ :charset => 'latin1', # The charset to set in mysqldump
21
+ :map_owner => true # Match database name, if name starts
22
+ # a users name, he's the owner
23
+ }
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jage-rmysqldump
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - "Johan Eckerstr\xC3\xB6m"
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-01-08 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: mysql
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ description: Used for dumping mysql databases on shared servers
26
+ email: johan@duh.se
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files: []
32
+
33
+ files:
34
+ - rmysqldump.conf
35
+ - bin/rmysqldump.rb
36
+ has_rdoc: false
37
+ homepage: http://github.com/jage/rmysqldump
38
+ post_install_message:
39
+ rdoc_options: []
40
+
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ requirements: []
56
+
57
+ rubyforge_project:
58
+ rubygems_version: 1.2.0
59
+ signing_key:
60
+ specification_version: 2
61
+ summary: Dump MySQL databases
62
+ test_files: []
63
+