Simple database backups using a nightly CRON job and Capistrano
2010/05/06 // Leeds // // Feed
Limerick Rake by Thoughbot provides a useful set of Rake tasks to help simplify common tasks. One that I use quite a lot is the backup task which performs a mysqldump of the specified environments’ database. It looks roughly like this:
# http://github.com/thoughtbot/limerick_rake/blob/master/tasks/backup.rake
# lib/tasks/backup.rake
namespace :application do
desc "Backs the applications database up for the given environment"
task :backup => :environment do
config = ActiveRecord::Base.configurations[RAILS_ENV || 'development']
database = config['database']
filename = "#{database.gsub(/_/, '-')}-#{Time.now.strftime('%Y-%m-%d-%H%M%S')}.sql"
backup_directory = File.expand_path(File.join(RAILS_ROOT, '..', '..', "shared", "backups"))
backup_path = File.join(backup_directory, filename)
binary = %x[ which mysqldump ].strip
options = "-e -u #{config['username']}"
options += " -p#{config['password']}" if config['password']
options += " -h #{config['host']}" if config['host']
raise RuntimeError, "I only work with mysql." unless config['adapter'] == 'mysql'
raise RuntimeError, "Cannot find mysqldump." if binary.blank?
FileUtils.mkdir_p(backup_directory)
puts "Backing up #{database}"
%x[ #{binary} #{options} #{database} > #{backup_path} ]
puts "Backed up #{database} => #{backup_path}"
end
end
There’s a couple of ways I like to use this. Firstly, to ensure that the database is cloned before a deploy using Capistrano. By hooking it into a before callback I can ensure the database is backed up before any code is updated:
# config/deploy.rb
namespace :deploy do
before "deploy:update_code", "deploy:backup"
desc "Backs up the applications database to RAILS_ROOT/../shared/backups"
task :backup do
run "cd #{deploy_to}current && rake application:backup RAILS_ENV=#{rails_env}"
end
end
This does the job for small to medium sized sites, larger ones would have much more rigourous backup procedures. Another way is to use it on a nightly CRON job, which might be more useful for preserving day-to-day snapshots of your database. In your crontab:
0 1 * * * cd /path/to/project && RAILS_ENV=production /usr/bin/env rake application:backup >> log/backup.log 2>&1
This way you cover your back between deploys and keep daily copies of the database should the worse ever happen.