読者です 読者をやめる 読者になる 読者になる

Rails Webook

自社のECを開発している会社で働いています。Rails情報やサービスを成長させる方法を書いていきます

RailsでCron設定をソース管理する!?wheneverを使ってCronを設定する

Rails初級 Rails gem

f:id:nipe880324:20150222115950j:plain
Photo by Flickr: nicadlr's Photostream

Cron設定を行えるgemのwheneverをRailsに導入する方法を説明します。

wheneverはRubyコードでCronの設定を行えるgemです。
これを使うことで、アプリケーションコードとCron設定を一緒にでき、ソース管理ができるのでCron設定の管理が楽になります。
他には、Chefなどのプロビジョニングツールを使いcrontabを設定する方法もあります。

使い分けとしては、Railsアプリケーションに依存するCron設定は「whenever」、アプリケーションに依存しないCron設定(例:ログローテート)は「プロビジョニングツール」に分けて記載するのがいいと思います。


動作確認

  • Rails 4.2.0
  • Ruby 2.2.0
  • whenever 0.9.4

目次

  1. wheneverのインストール
  2. wheneverの基本的な使い方
  3. schedule.rbのサンプル


wheneverのインストール

Gemfileに追加します。

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


バンドルを実行します。

bundle install


wheneverでCronの設定を記載するファイル(/config/schedule.rb)を作成します。

bundle exec wheneverize
  [add] writing `./config/schedule.rb'
  [done] wheneverized!


wheneverの基本的な使い方

作成したschedule.rbにCronの設定を記載します。

# config/schedule.rb
# コマンドの出力先を設定(デフォルトはなし)
set :output, "#{path}/log/cron.log"

# コマンドを実行するシェルを設定する(デフォルトはbash -l -c ':job')
# set :job_template, "zsh ':job'"

# RAILS_ENVを設定する(デフォルトはproduction)
# set :environment, "development"


# 毎日の午前1時30分に実行する
every 1.day, at: '1:30 am' do
  command "/usr/bin/some_great_command"
  runner "MyModel.some_method"
  rake "some:great:rake:task"
end

# 毎日曜日の昼の12時に実行する
every :sunday, at: '12pm' do
  runner "AnotherModel.prune_old_records"
end

記載は難しくなく、everyメソッドで時間を指定し、ブロック内で実行するコマンドを記載します。
実行するコマンドは、「コマンドを実行するcommand」、「rails runnderを実行するrunnder」、「Rakeタスクを実行するrake」があります。


では、wheneverコマンドを実行して、crontabの設定をします。

// schedule.rb をcrontabの文法に変換する(crontabへの書き込みは行わない)
$ bundle exec whenever
30 1 * * * /bin/bash -l -c '/usr/bin/some_great_command >> /Users/nipe/GoogleDrive/rails/rails_samples/cron_test/log/cron.log 2>&1'

30 1 * * * /bin/bash -l -c 'cd /Users/nipe/GoogleDrive/rails/rails_samples/cron_test && bin/rails runner -e production '\''MyModel.some_method'\'' >> /Users/nipe/GoogleDrive/rails/rails_samples/cron_test/log/cron.log 2>&1'

30 1 * * * /bin/bash -l -c 'cd /Users/nipe/GoogleDrive/rails/rails_samples/cron_test && RAILS_ENV=production bundle exec rake some:great:rake:task --silent >> /Users/nipe/GoogleDrive/rails/rails_samples/cron_test/log/cron.log 2>&1'

0 12 * * 0 /bin/bash -l -c 'cd /Users/nipe/GoogleDrive/rails/rails_samples/cron_test && bin/rails runner -e production '\''AnotherModel.prune_old_records'\'' >> /Users/nipe/GoogleDrive/rails/rails_samples/cron_test/log/cron.log 2>&1'

## [message] Above is your schedule file converted to cron syntax; your crontab file was not updated.
## [message] Run `whenever --help' for more options.


// crontabを更新する(既に書かれているcron設定は消えない)
$ bundle exec whenever -i


// crontabを上書きする(既に書かれているcron設定は消える)
$ bundle exec whenever -w


schedule.rbのサンプル

schedule.rbのcron設定の記載方法のサンプルです。

every 3.hours do
  runner "MyModel.some_process"
  rake "my:rake:task"
  command "/usr/bin/my_great_command"
end

every 1.day, :at => '4:30 am' do
  runner "MyModel.task_to_run_at_four_thirty_in_the_morning"
end

every :hour do # 他にも :hour, :day, :month, :year, :rebootが使えます
  runner "SomeModel.ladeeda"
end

every :sunday, :at => '12pm' do # 他の曜日(:mondayなど)、:weekend、:weekdayが使えます
  runner "Task.do_something_great"
end

every '0 0 27-31 * *' do   # 通常のcronの文法も使えます
  command "echo 'you can use raw cron syntax too'"
end

# Capistranoの:appロールのみで実行されます
every :day, :at => '12:20am', :roles => [:app] do
  rake "app_server:task"
end

他には、capistrano3と連携してcronの設定を行う方法などもあります。

以上です。