Ruby/Ruby on Rails/デプロイ/Capistrano
Rails環境でDB(MySQL)のバックアップとリストアをCapistranoから自動化する方法を書いてみます。
Capistrano v2.5.5、クライアントはWindows XP、サーバー側はUbuntu 8.04で確認しました。
上記のようなのを想定してます…。
例えば以下のようにconfig/deploy.rbに追記で書いてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | before "deploy:migrate", "backup:mysql" # バックアップ用 namespace :backup do desc "Backup remote production DB with mysqldump" task :mysql, :roles => :db, :only => { :primary => true } do require 'yaml' filename = "#{application}.#{domain.gsub(".", "_")}.#{Time.now.strftime("%Y-%m-%d_%H-%M-%S")}.sql.bz2" file = "#{shared_path}/backups/#{filename}" on_rollback { delete file } # DBの設定読み込み db = YAML::load(ERB.new(IO.read(File.join(File.dirname(__FILE__), 'database.yml'))).result)['production'] # フォルダ作成 run "mkdir -p #{shared_path}/backups" # MYSQL dump run "mysqldump -u #{db['username']} --password=#{db['password']} #{db['database']} | bzip2 -c > #{file}" do |ch, stream, data| puts data end # 手元に持ってくる backup_dir = File.dirname(__FILE__) + "/../../backups/" FileUtils.mkdir_p backup_dir get file, "#{backup_dir}/#{filename}" end desc "Restore DB by mysqldumped mysql file(-S sql=dumpled_filename)" task :restore_mysql, :roles => :db do filename = sql unless sql # (実は意味なし)そもそも-S sql=〜〜で書かないとsqlないと言われてエラーになる abort "error: specified -S=dumped_filename" end unless Capistrano::CLI.ui.agree("Confirm replace and restore DB data? (y/n)") abort "Restore Canceled..." end file = "#{filename}" filename_only = File::basename(filename) # tmp/~~~~.sql.bz2 out_file = "/tmp/#{filename_only}" # tmp/~~~~.sql out_sql_file = File.join(File::dirname(out_file), File::basename(out_file, ".*")) # すでにファイルがあると解凍できないので消しとく run "rm #{out_sql_file}; true" #on_rollback { delete out_file; delete out_sql_file } # DBの設定読み込み db = YAML::load(ERB.new(IO.read(File.join(File.dirname(__FILE__), 'database.yml'))).result)['production'] # bz2転送 upload file, out_file # 解凍 run "bunzip2 #{out_file}" # リストア run "mysql #{db['database']} -u #{db_user} -p#{db['password']} < #{out_sql_file}" run "rm #{out_sql_file}; true" end end |
上記のように書いてみた時の使い方
cap deploy:cold コマンドでdb:migrate前に自動でDBをバックアップできます。
cap deploy:coldするとrake db:migrateが走りますが、
migrate前に自動でmysqldumpしてbz2で固めてshared/backupsにアプリ名、ドメイン名、日時でファイル名をつけてDBのバックアップを置いてくれます。
また、プロジェクトのディレクトリ上の backups/ディレクトリにも同じファイルをリモートからコピーしてきます。
つまり、
ということになります。
手動でバックアップする場合は、
cap backup:mysql
すると、上記の自動バックアップで書いた事をその場で手動で実行できます。
(もちろん、rake db:migrateは実行されません)
バックアップしたデータをリストアもできます。
cap backup:restore_mysql -S=(backup:mysqlでバックアップした〜.sql.bz2のファイル名)
つまり、
cap backup:restore_mysql -S=../../backup/myapp.foo_bar_com.2009-12-17-00_01_12.sql.bz2
などのように、最後に -S=(sql.bz2ファイル名)のとともにDBのバックアップをbz2で固めたもの(上記backup:mysqlでバックアップしたもの)を指定します。
※-S=を指定しないとわかりにくいエラーがでてしまいます。
なお、コマンド実行前には念のため、
Confirm replace and restore DB data? (y/n)
などと確認がでるので、yを押して<ENTER> を押してください。
間違った場合は、Ctrl+Cかnを押せば大丈夫です、まだ間に合います。
No comment. Comments/Ruby/Ruby on Rails/デプロイ/Capistrano/MySQLのバックアップとリストア?