Railsでwheneverを使って定期的にタスクを実行する方法

プログラミング
2019年06月24日 10:00

概要

RailsでWebアプリケーションを作成した際に、定期的に実行したい処理がある事があると思います。
そのような時には、whenerverというgemを使う事で定期的に処理を実行する事ができるようになります。

今回は、このRailsでwheneverを使って定期的に処理を実行する方法を紹介します。

環境

  • Rails 5.2
  • whenever 1.0.0

wheneverはRailsだけではなくRubyでも使う事ができますが、今回はRailsに焦点を絞って説明をします。

インストール

wheneverはRubygemsで公開されているので、Gemfileに次のように書きます。

gem 'whenever', require: false

require: falseとしているのは、Railsの内部でwheneverを使うわけではないため、Railsの実行時に読み込まないようにするためです。

次のコマンドでインストールします。

bundle install

詳細は述べませんが、wheneverは実際にはcronを使って定期的に処理を実行します。
そのため、Railsを実行する環境でcronがインストールされている必要があります。
しかし、ほとんどのLinuxやmacOSなどの環境ではcronがインストールされている事がほとんどのため、特別何かするということはないと思います。
cronのインストールの仕方についてはここでは述べません。

設定

次のコマンドでwheneverで使う設定ファイルを作成します。

$ wheneverize

設定ファイルはconfig/schedule.rbに作成されます。

設定の例として、GitHubにあるwheneverのREADME.mdに書かれているサンプルを次に載せておきます。

every 3.hours do # 1.minute 1.day 1.week 1.month 1.year is also supported
  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 1.day, at: ['4:30 am', '6:00 pm'] do
  runner "Mymodel.task_to_run_in_two_times_every_day"
end

every :hour do # Many shortcuts available: :hour, :day, :month, :year, :reboot
  runner "SomeModel.ladeeda"
end

every :sunday, at: '12pm' do # Use any day of the week or :weekend, :weekday
  runner "Task.do_something_great"
end

every '0 0 27-31 * *' do
  command "echo 'you can use raw cron syntax too'"
end

見ただけでも、なんとなく使い方が分かるような感じがします。

詳しく説明すると、まずeveryで定期的に実行したい処理を記述します。
everyの引数では、どのような頻度で実行するのかを記述します(1.dayとか3.dayとか)。
この時atを使えば、具体的な時刻を指定できます。
またcronと同じ形式で時刻を指定することもできます。

everyの引数の最後では、実際に実行する処理を記述したブロックを渡します。

このようにして処理を実行したい処理を記述します。

実行

設定しただけでは定期的に処理を実行することはできません。

wheneverは内部ではcronを使っています。次のコマンドでは設定ファイルをもとにcronの設定ファイルとして定期的に実行するタスクを生成します。

$ whenever --update-crontab

これで、wheneverからcronの方へ反映できたので、定期的にタスクが実行されます。
また、schedule.rbを変えた場合は、毎回実行して反映させるのを忘れないようにしましょう。

さいごに

慣れてしまえば、簡単に設定する事ができます。

私自身、cronへの反映を忘れてしまったという経験があるので気をつけましょう。