しめ鯖日記

swift, iPhoneアプリ開発, ruby on rails等のTipsや入門記事書いてます

Railsでcrontabを管理できるwheneverというGemを使ってみる

Railsを使っていると「日時バッチ」「1時間に一度の処理」など定期的に実行したいタスクが出てきます。
管理方法としては普通にcrontabに書き込んだりJenkinsなどを使ってそれらのタスクを管理する方法があります。
しかし可能ならRailsプロジェクト上で実行時間なども管理したいです。

そういった時に使えるGemがwheneverです。
これを使うと下のようにRubyでcrontabの管理ができます。

every :day, at: '12:20' do
  runner 'MyModel.execute'
end

every :sunday, at: '12:30'
  runner 'MyModel2.execute'
end

github.com

wheneverを使う準備

インストールはBundlerを使います。

gem 'whenever'

インストールが終わったらwheneverizeコマンドでwheneverの初期化をします。

wheneverize

f:id:llcc:20180716215520p:plain

実行するとconfig/schedule.rbというファイルが作られます。
ファイルの内容は下の通りです。

# Use this file to easily define all of your cron jobs.
#
# It's helpful, but not entirely necessary to understand cron before proceeding.
# http://en.wikipedia.org/wiki/Cron

# Example:
#
# set :output, "/path/to/my/cron_log.log"
#
# every 2.hours do
#   command "/usr/bin/some_great_command"
#   runner "MyModel.some_method"
#   rake "some:great:rake:task"
# end
#
# every 4.days do
#   runner "AnotherModel.prune_old_records"
# end

# Learn more: http://github.com/javan/whenever

wheneverの使い方

まずは先程作られたconfig/schedule.rbに定期実行したいタスクを書きます。
下は4日おきにMyModelのcreate!を呼び出すタスクです。

every 4.days do
  runner "MyModel.create!"
end

タスクを書いたらcrontabにどんな形で書き込まれるか確認をします。
確認にはwheneverコマンドを使います。

whenever

wheneverコマンドを実行すると下のようにどのようにcrontabに書き込まれるかが表示されます。

f:id:llcc:20180716220541p:plain

crontabへの反映もwheneverコマンドを使います。
下のように--update-crontabを付けて実行します。

whenever --update-crontab

実行後crontab -lで確認するとしっかり書き込みができている事が分かります。

f:id:llcc:20180716220757p:plain

wheneverのフォーマット

wheneverではデフォルトでcommand, rake, runner, scriptというメソッドが用意されています。
実行結果はそれぞれ下の通りです。

every 4.days do
  command "bundle install" # → /bin/bash -l -c 'bundle install'
  rake "my_task" # → /bin/bash -l -c 'cd /Users/xxxx/Desktop/my_app && RAILS_ENV=production bundle exec rake my_task --silent'
  runner "MyModel.create!" # → /bin/bash -l -c 'cd /Users/xxxx/Desktop/my_app && bundle exec bin/rails runner -e production '\''MyModel.create!'\'''
  script "my_script" # → /bin/bash -l -c 'cd /Users/xxxx/Desktop/my_app && RAILS_ENV=production bundle exec script/my_script'
end

自分で上記以外のメソッドを追加する事もできます。

job_type :my_job, "cd :path && :bundle_command rake :task"

every 4.days do
  my_job "my_task" # → /bin/bash -l -c 'cd /Users/xxxx/Desktop/my_app && bundle exec rake my_task'
end

実行時間の書き方も色々な種類があります。

下のように文字列でcrontabと同じ形式に書く事ができます。
非常に分かりやすい書き方です。

every '0 0,1,2 * * *' do # → 0 0,1,2 * * *
  runner 'MyModel.execute'
end

毎日決まった時間に実行する場合は下のような書き方も分かりやすいです。

every :day, at: '12:20' do # → 20 12 * * *
  runner 'MyModel.execute'
end

特定の曜日だけ実行する事もできます。

every :sunday, at: '12:30' do # → 30 12 * * 0
  runner 'MyModel.execute'
end