40
36

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Mysqlバックアップrakeタスクを作ってwheneverで回すまで

Posted at

mysqlのバックアップ用rakeタスクを作成する

ここを参考にしながら、mysqlデータベースをaws s3にバックアップを行なうためのrakeタスクを書いた。そしてそれをwheneverで定期的に実行するようにしてデータベースのバックアップ体制を取りました。ここのスクリプトでは、dotenvaws-sdkに依存しています。dotenvを使用している部分はよしなに環境変数を使用するように変更すると良いと思います。

Railsでデータベースのバックアップを取るためのgemとしてbackupっていうgemもあるのですが、設定が色々と面倒くさそうだったので、ミニマムに自分で書いた方が早そうだと思って自分でスクリプト書く次第となりました。

とりあえずで書いたので、DRYになってないのでリファクタリング掛けたい所。

lib/tasks/backup.rb
require 'dotenv/tasks'

namespace :backup do

  desc "nightly backup"
  task :nightly => :dotenv do
    timestamp = Time.now.strftime("%Y-%m-%d_%H-%M-%S")
    backup_file = "tmp/backups/#{timestamp}_dump.sql.gz"
    `mkdir -p tmp/backups`
    `mysqldump -u #{ENV['DB_USERNAME']} -p#{ENV['DB_PASSWORD']} #{ENV['DB_NAME']} | gzip -c > #{backup_file}`

    send_to_s3_nightly backup_file
  end

  desc "weekly backup"
  task :weekly => :dotenv do
    timestamp = Time.now.strftime("%Y-%m-%d_%H-%M-%S")
    backup_file = "tmp/backups/#{timestamp}_dump.sql.gz"
    `mkdir -p tmp/backups`
    `mysqldump -u #{ENV['DB_USERNAME']} -p#{ENV['DB_PASSWORD']} #{ENV['DB_NAME']} | gzip -c > #{backup_file}`

    send_to_s3_weekly backup_file
    delete_olds
  end

  def delete_olds(num = 10)
    bucket = get_bucket
    bucket.objects.with_prefix("backups/nightly/").each do |backup|
      datestr = backup.key.match(/[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}/)[0]
      date = DateTime.strptime(datestr,"%Y-%m-%d_%H-%M-%S")
      if (Date.today - num).to_datetime > date
        backup.delete
      end
    end

    bucket.objects.with_prefix("backups/weekly/").each do |backup|
      datestr = backup.key.match(/[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}/)[0]
      date = DateTime.strptime(datestr,"%Y-%m-%d_%H-%M-%S")
      if (Date.today - num * 7).to_datetime > date
        backup.delete
      end
    end
  end

  def send_to_s3_nightly(file_path)
    bucket = get_bucket
    file_name = File.basename(file_path)
    bucket.objects["backups/nightly/#{file_name}"].write(File.open("#{file_path}"))
  end

  def send_to_s3_weekly(file_path)
    bucket = get_bucket
    file_name = File.basename(file_path)
    bucket.objects["backups/weekly/#{file_name}"].write(File.open("#{file_path}"))
  end

  def get_bucket
    s3 = AWS::S3.new(
      access_key_id: ENV["AWS_ACCESS_KEY_ID"],
      secret_access_key: ENV["AWS_SECRET_ACCESS_KEY"],
      s3_endpoint: ENV['S3_HOST_NAME']
    )
    bucket = s3.buckets[ENV['S3_BUCKET_NAME']]
    bucket = s3.buckets.create(ENV['S3_BUCKET_NAME']) unless bucket.exists?
    bucket
  end
end

wheneverで定期的に実行する

先ほど書いたrakeタスクをwheneverで毎日、毎週走らせます。こちらを参考に導入しましたが、導入が簡単で良いですね。

まずは、wheneverをGemfileに追加

Gemfile
+ gem 'whenever', :require => false

wheneverの設定ファイルを生成するコマンドが付いてくるので、実行します。

cd path/to/project_dir/
wheneverize .

先ほど生成された設定ファイルconfig/schedule.rbに設定を書いて行きます。capistranoと連携させるために、roleを記述しています。

config/schedule.rb
# 出力先のログファイルの指定
set :output, 'log/crontab.log'
# ジョブの実行環境の指定
set :environment, :production

# 毎日 am4:30のスケジューリング
every 1.day, :at => '4:30 am', :roles => [:db] do
  rake "backup:nightly"
end

# 日曜日のpm12時にスケジューリング
every :monday, :at => '4am', :roles => [:db] do
  rake "backup:weekly"
end

capistrano v3でデプロイ時にwheneverを設定するようにする

Capfile
+require "whenever/capistrano"
+SSHKit.config.command_map[:whenever] = "bundle exec whenever"
config/deploy.rb
set :whenever_environment, "#{fetch(:stage)}" #wheneverでの環境指定に必要
set :whenever_identifier, ->{ "#{fetch(:application)}_#{fetch(:stage)}" } #cronjobのユニークを保つために必要

これで、デプロイの設定は終了。あとは

bundle exec cap production deploy

すれば、自動でwheneverの設定を反映させてくれます。

40
36
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40
36

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?