Active Record YAML Backup Solution - Drop in rake task and config file to backup db and directorys of your choice (user uploaded files)
backs up db and any directory's to any number of servers with rsync
BSD License or whatever, but it would be cool if you told me your using it
2007 ISS http://industrialstrengthinc.com
this is a sample config file and a rake task you can drop into any rails project to do backups, easy to automate.
Backs up your specified environment db to activerecord yml files (one per table) and zips them up in a human readable timestamped file
syncs that and any other set of arbitrary directory's to any number of arbitrary servers with rsync
be sure to set ssh key based logins
to run: rake backup
also: rake backup:db, rake backup:restoredb (promts for a file created by backup:db), rake backup:push (to push out what u got)
note: this uses something like 30 lines of code from some blog site I got it from that I cant recall, yay for that guy, thanks
1 2 ## example crontab entry: 3 4 3 * * * * cd /rails_deployment_dir/current && nice rake backup RAILS_ENV=production >> /rails_deployment_dir/production_backup_system.log 5 6 ## config file - goes in config/backup.yml 7 8 production: 9 dirs: 10 - db/backups 11 - public/uploaded_images 12 servers: 13 - name: backup server number 1 14 host: gridserver.com 15 port: 22 16 user: blah@whatever.com 17 dir: /home/blah/backups 18 - name: backup server two 19 host: kradradio.com 20 port: 22 21 user: kraduser 22 dir: /home/kraduser/backups_from_my_rails_proj 23 24 25 development: 26 dirs: 27 - db/backups 28 - public/uploaded_images 29 servers: 30 - name: local self 31 host: localhost 32 port: 5222 33 user: oneman 34 dir: /home/oneman/Documents/development_backup 35 36 37 ## rake file lib/tasks/backup.rake 38 39 desc "Backup Everything Specified in config/backup.yml" 40 task :backup => [ "backup:db", "backup:push"] 41 42 namespace :backup do 43 44 RAILS_APPDIR = RAILS_ROOT.sub("/config/..","") 45 46 def interesting_tables 47 ActiveRecord::Base.connection.tables.sort.reject! do |tbl| 48 ['schema_info', 'sessions', 'public_exceptions'].include?(tbl) 49 end 50 end 51 52 desc "Push backup to remote server" 53 task :push => [:environment] do 54 FileUtils.chdir(RAILS_APPDIR) 55 backup_config = YAML::load( File.open( 'config/backup.yml' ) )[RAILS_ENV] 56 for server in backup_config["servers"] 57 puts "Backing up #{RAILS_ENV} directorys #{backup_config['dirs'].join(', ')} to #{server['name']}" 58 puts "Time is " + Time.now.rfc2822 + "\n\n" 59 for dir in backup_config["dirs"] 60 local_dir = RAILS_APPDIR + "/" + dir + "/" 61 remote_dir = server['dir'] + "/" + dir.split("/").last + "/" 62 puts "Syncing #{local_dir} to #{server['host']}#{remote_dir}" 63 sh "/usr/bin/rsync -avz -e 'ssh -p#{server['port']} ' #{local_dir} #{server['user']}@#{server['host']}:#{remote_dir}" 64 end 65 puts "Completed backup to #{server['name']}\n\n" 66 end 67 end 68 69 task :storedb => :environment do 70 71 backupdir = RAILS_APPDIR + '/db/backup' 72 FileUtils.mkdir_p(backupdir) 73 FileUtils.chdir(backupdir) 74 puts "Dumping database to activerecord yaml files in #{backupdir}" 75 interesting_tables.each do |tbl| 76 77 klass = tbl.classify.constantize 78 puts "Writing #{tbl}..." 79 File.open("#{tbl}.yml", 'w+') { |f| YAML.dump klass.find(:all).collect(&:attributes), f } 80 end 81 puts "Database Dumped.\n\n" 82 end 83 84 desc "Dump Current Environment Db to file" 85 task :db => [:environment, :storedb ] do 86 backupdir = RAILS_APPDIR + '/db/backup' 87 archivedir = RAILS_APPDIR + '/db/backups' 88 backup_filename = "#{RAILS_ENV}_db_backup_#{Time.now.strftime("%B.%d.%Y_at_%I.%M.%S%p_%Z")}.tar.bz2" 89 FileUtils.mkdir_p(archivedir) 90 puts "Archiving #{backupdir} yaml files to #{backup_filename}\n\n" 91 `tar -C #{backupdir} -cjf #{backup_filename} *` 92 `mv #{backup_filename} #{archivedir}` 93 end 94 95 desc "Restore Current Environment Db from a file" 96 task :restoredb => [:environment] do 97 backupdir = RAILS_APPDIR + '/db/backup' 98 archivedir = RAILS_APPDIR + '/db/backups' 99 print "Input a file to load into the db: #{archivedir}/" 100 backup_filename = STDIN.gets.chomp 101 puts "Loading backup file: #{backup_filename}" 102 FileUtils.chdir(archivedir) 103 `tar -xjf #{backup_filename}` 104 `mv *.yml #{backupdir}` 105 FileUtils.mkdir_p(backupdir) 106 FileUtils.chdir(backupdir) 107 108 interesting_tables.each do |tbl| 109 puts "Clearing #{tbl} table.." 110 ActiveRecord::Base.connection.execute "TRUNCATE #{tbl}" 111 puts "Loading #{tbl} backup file..." 112 table = YAML.load_file("#{tbl}.yml") 113 114 if table.length > 0 && table.first.key?("id") 115 highestid = 0 116 table.each do |fixture| 117 if fixture["id"] > highestid 118 highestid = fixture["id"] 119 end 120 end 121 122 ActiveRecord::Base.connection.execute "SELECT setval('#{tbl}_id_seq',#{highestid})" 123 puts "Setting #{tbl}_id sequence to #{highestid}" 124 end 125 126 #klass = tbl.classify.constantize 127 ActiveRecord::Base.transaction do 128 129 puts "Inserting #{table.length} values into #{tbl}" 130 table.each do |fixture| 131 ActiveRecord::Base.connection.execute "INSERT INTO #{tbl} (#{fixture.keys.join(",")}) VALUES (#{fixture.values.collect { |value| ActiveRecord::Base.connection.quote(value) }.join(",")})", 'Fixture Insert' 132 end 133 puts "#{tbl} table restored.\n\n" 134 end 135 end 136 end 137 138 139 end