Skip to content

Commit 336f9ef

Browse files
committedMay 27, 2011
Initial commit.
0 parents  commit 336f9ef

File tree

2 files changed

+145
-0
lines changed

2 files changed

+145
-0
lines changed
 

‎README.md

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# What it does
2+
3+
This script can be used to backup MySQL databases that are stored on an EBS volume using XFS.
4+
5+
# Requirements
6+
7+
* xfsprogs
8+
* mysql
9+
* ruby
10+
* rubygems
11+
** mysql
12+
** open4
13+
** fog
14+
** active_support
15+
16+
# Configuration
17+
18+
Open the script in your favourite editor and fill out the following fields
19+
20+
```ruby
21+
# Amazon AWS Configuration
22+
AWS_ACCESS_KEY_ID = ''
23+
AWS_SECRET_ACCESS_KEY = ''
24+
AWS_VOLUME = '' # EBS volume to make snapshots of
25+
26+
# MySQL Configuration
27+
MYSQL_HOST = ''
28+
MYSQL_USERNAME = ''
29+
MYSQL_PASSWORD = ''
30+
```
31+
32+
Then simply store the script in /etc/cron.hourly and you're done!

‎mysql-snapshot.rb

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
require 'rubygems'
2+
require 'mysql'
3+
require 'open4'
4+
require 'fog'
5+
require 'active_support'
6+
7+
# Amazon AWS Configuration
8+
AWS_ACCESS_KEY_ID = ''
9+
AWS_SECRET_ACCESS_KEY = ''
10+
AWS_VOLUME = '' # EBS volume to make snapshots of
11+
12+
# MySQL Configuration
13+
MYSQL_HOST = ''
14+
MYSQL_USERNAME = ''
15+
MYSQL_PASSWORD = ''
16+
17+
class Time
18+
%w(to_date to_datetime).each do |method|
19+
public method if private_instance_methods.include?(method)
20+
end
21+
end
22+
23+
now = Time.now
24+
today = now.to_date
25+
hr24 = (now - 86400)
26+
27+
# Connect to MySQL
28+
puts 'Connecting to MySQL...'
29+
my = Mysql::new(MYSQL_HOST, MYSQL_USERNAME, MYSQL_PASSWORD)
30+
31+
# Connect to AWS
32+
puts 'Connecting to AWS...'
33+
compute = Fog::Compute.new(:provider => 'AWS',
34+
:aws_access_key_id => AWS_ACCESS_KEY_ID,
35+
:aws_secret_access_key => AWS_SECRET_ACCESS_KEY)
36+
37+
# Stop replication
38+
puts 'Stopping MySQL Replication...'
39+
my.query('STOP SLAVE')
40+
41+
# Lock the table(s)
42+
puts 'Locking MySQL Tables...'
43+
my.query('FLUSH TABLES WITH READ LOCK')
44+
45+
# Sync the filesystem
46+
puts 'Syncing the filesystem...'
47+
status = Open4::popen4('sync') do |pid, stdin, stdout, stderr|
48+
# Wait for the command to finish executing; handle any errors
49+
# TODO: Add e-mail / ticket support if an error occurs
50+
end
51+
52+
# XFS Freeze
53+
puts 'Freezing XFS...'
54+
status = Open4::popen4('xfs_freeze -f') do |pid, stdin, stdout, stderr|
55+
# Wait for the command to finish executing; handle any errors
56+
# TODO: Add e-mail / ticket support if an error occurs
57+
end
58+
59+
# Create new EBS Snapshot
60+
puts 'Creating a new EBS Snapshot...'
61+
snap = compute.snapshots.new :volume_id => AWS_VOLUME, :description => 'MySQL Backup'
62+
puts 'Saving the new EBS Snapshot...'
63+
snap.save
64+
65+
# XFS Unfreeze
66+
puts 'Unfreezing XFS...'
67+
status = Open4::popen4('xfs_freeze -u') do |pid, stdin, stdout, stderr|
68+
# Wait for the command to finish executing; handle any errors
69+
# TODO: Add e-mail / ticket support if an error occurs
70+
end
71+
72+
# Unlock the table(s)
73+
puts 'Unlocking MySQL Tables...'
74+
my.query('UNLOCK TABLES')
75+
76+
# Start replication
77+
puts 'Starting MySQL Replication...'
78+
my.query('START SLAVE')
79+
80+
# Delete old EBS Snapshot(s)
81+
puts 'Deleting old EBS Snapshots...'
82+
snaps = compute.snapshots.all.collect do |s|
83+
if s.volume_id == AWS_VOLUME
84+
if s.progress == '100%'
85+
[s.id, Time.parse(s.created_at.to_s)]
86+
end
87+
end
88+
end
89+
90+
# Remove nil entries
91+
snaps.delete_if do |s|
92+
s == nil
93+
end
94+
95+
# Remove entries from the past 24 hours
96+
snaps.delete_if do |s|
97+
s.last >= hr24
98+
end
99+
100+
# Keep only one from each day
101+
dated = snaps.group_by do |s|
102+
s.last.to_date
103+
end
104+
105+
today.downto(today - 7) do |date|
106+
dated[date].delete dated[date].sort_by(&:last).last if dated[date]
107+
end
108+
109+
deleting = dated.inject([]) { |a,(k,v)| a << v.map(&:first) }.flatten
110+
111+
deleting.each do |snap|
112+
compute.snapshots.get(snap).destroy
113+
end

0 commit comments

Comments
 (0)
Please sign in to comment.