2011年7月7日木曜日

crontabを設定するプラグイン「whenever」

Railsの機能を使った処理を簡単にcrontabに設定するプラグイン「whenever」があります。DSLによって、Rubyライクな書き方でcrontabを設定できるのが特徴です。

whenever

mysqlのバックアップを定期的に行うプログラムを使って、バッチ処理を組み込む方法を紹介します。

まずバッチ処理を記述します。ファイル名「lib/batch_backup.rb」とします。
# coding: utf-8
class BatchBackup
  def self.execute
    backup_database
  end

  # データベースのバックアップ
  def self.backup_database
    env = Rails.env
    # バックアップファイルを格納するフォルダ(作っておく)
    location = "~/backup/database/"
    password = mypassword
    backup_file = "myapp_#{env}_#{Date.today.strftime("%Y%m%d")}.sql"

    command = "mysqldump myapp_#{env} > #{location}#{backup_file} -u root -p#{password}"
    system(command)
end
私はバッチ処理プログラムをlibフォルダに格納します。このままではRailsはこのファイルを起動時に読み込まないので、config/application.rbに下記を追加します。
config.autoload_paths += %W(#{Rails.root}/lib)
次にwheneverの設定を行います。インストールは
$ sudo gem install whenever
か、Gemfileに下記を追加して、sudo bundle installするかのいずれかを選択します。
gem "whenever", :require => false
インストールが完了したら、wheneverの初期設定です。Railsのルートフォルダで下記を実行します。
$ wheneverize .
すると、config/schedule.rbが作成されます。ここにcrontabに設定したバッチ処理を記述します。
set :output, "/home/rails/myapp/cron_log"

every 1.day, :at => '5:00am' do
  runner "BatchBackup.execute"
end
ここでは毎日5:00にこのバッチ処理を実行するように記述しています。

また、cronの実行ログを出力するため「set :output」を指定しています。cronの実行ログは(ubuntuの場合)/var/log/syslogに記述されていますが、プログラム上の問題を出力するにはこれが必要になります。

次にcapistranoでデプロイした際、バッチ処理を設定するようにconfig/deploy.rbを編集します。
ここではwheneverが用意したcapistrano用のレシピファイルを使うことにします。config/deploy.rbに下記を追記します。
require "whenever/capistrano"
これでcap deployしたときに自動でcrontabに設定してくれるようになります。

では、サーバーへアップします。
$ git add .
$ git commit -a -m "バックアップバッチ処理を追加"
$ git push origin master
$ cap deploy
次にサーバーへアクセスして設定できているかチェックします。
$ ssh rails@mydomain.jp
$ crontab -l
設定されていれば下記のように表示されると思います。
0 5 * * * /bin/bash -l -c 'cd /var/rails/myapp/releases/xxxxxxxxxxxxx && script/rails runner -e production '\''BatchBackup.execute'\'' >> /home/rails/myapp/cron_log 2>&1'
これでOKです。

ちなみに私はこの先ではまってしまいました。
~/myapp/cron_logに下記のようなエラーが出力されていました。
/usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require': no such file to load -- bundler/setup (LoadError)
        from /usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `require'
        from /var/rails/myapp/releases/xxxxxxxxxxxxxx/config/boot.rb:6
        from script/rails:5:in `require'
        from script/rails:5
どうやらバッチ処理を実行する際、以前使用していたRuby 1.8のgemを見に行っているようです。

そこでconfig/schedule.rbに実行時のパスの指定を行います。
set :output, "/home/rails/myapp/cron_log"
env :PATH, "/usr/local/bin:/usr/bin:/bin" # <= 追加

every 1.day, :at => '5:00am' do
  runner "BatchBackup.execute"
end
これで動作するようになりました!

<参考>
http://stackoverflow.com/questions/5698028/whenever-path-in-crontab-file-for-rails-3-ubuntu

0 件のコメント:

コメントを投稿