A Rake Task for Database Backups

Posted by Craig Ambrose on March 01, 2007 at 12:54 AM

I wrote this little rake task for a client yesterday, and it seems handy enough that it’s worth disseminating. It doesn’t, however, seem to justify a plugin as yet.

Before doing this, I did search through the lists of rails plugins to see if there was a solution for backup up databases. I was fairly surprised to find that there wasn’t. Yes, to some extent this is our hosting provider’s responsibility. However, they often charge to retrieve backups, and might not give us the fine grained control that we are after.

To use this task, add the following code to a rakefile somewhere. I created a file called backup.rake, and put it inside /lib/tasks.

The Code


require 'find'namespace :db do desc "Backup the database to a file. Options: DIR=base_dir RAILS_ENV=production MAX=20"
task :backup => [:environment] do
datestamp = Time.now.strftime("%Y-%m-%d_%H-%M-%S") base_path = ENV["DIR"] || "db"
backup_base = File.join(base_path, 'backup')
backup_folder = File.join(backup_base, datestamp)
backup_file = File.join(backup_folder, "#{RAILS_ENV}_dump.sql.gz") File.makedirs(backup_folder) db_config = ActiveRecord::Base.configurations[RAILS_ENV] sh "mysqldump -u #{db_config['username']} -p#{db_config['password']} -Q —add-drop-table -O add-locks=FALSE -O lock-tables=FALSE #{db_config['database']} | gzip -c > #{backup_file}" dir = Dir.new(backup_base)
all_backups = dir.entries[2..-1].sort.reverse
puts "Created backup: #{backup_file}" max_backups = ENV["MAX"].to_i || 20
unwanted_backups = all_backups[max_backups..-1] || []
for unwanted_backup in unwanted_backups
FileUtils.rm_rf(File.join(backup_base, unwanted_backup))
puts "deleted #{unwanted_backup}"
end
puts "Deleted #{unwanted_backups.length} backups, #{all_backups.length - unwanted_backups.length} backups available"
endend

Usage

Here’s how the new backup rake task works. You call it with:

rake db:backup

Options

It has a few possible options, I’ll give an example first, then explain:

rake db:backup DIR=/home/sugarstats RAILS_ENV=production MAX=10

The DIR option specifies the base directory for the backups. I create a “backup” directory inside that, so you don’t need to include that on your path. This actually defaults to “db” inside the application, but you will want to overwrite it with the option above.

RAILS_ENV should be set to production. It is probably development by default.

MAX is the number of backups to keep. It defaults to 20, which I think is a nice safe number. Once this number of backups is exceeded, older backups are deleted. There’s no way to turn this off, other than removing that bit of code.

In Production

You’ll want to call this from cron. Like all rake tasks, it’s expecting to be run from the application directory, so the cron task needs to change the directory first. I’ve found that "cd /app_dir && rake db:migrate" works well, but you should test your cron task is working. I’m always getting cron tasks wrong.

Credits

This code was paid for by Marston Alfred, over at Sugarstats and is used in production for that site. Sugarstats is a website to help diabetics manage their sugar levels, activities, and medication, and is well worth a look (even if I do say so myself).

Post continues, click to read more...

Comments: 23 (view/add your own) Tags: (none)