CTC 教育サービス
[IT研修]注目キーワード Python UiPath(RPA) 最新技術動向 Microsoft Azure Docker Kubernetes
こんにちは。 ゼネットの藺藤です。
さて、みなさんは"自動化"はお好きですか? 私は好きです。(*1) 今回のコラムでは、Rails上で定期実行するジョブの管理に便利なGem、「Whenever」を紹介します。(*2,*3,*4)
Linux系OSでは、定期的にジョブを実行するための仕組みとしてcron (crontab)が用意されていますが、「Whenever」はcronの仕組みをより扱いやすいようにRubyを使って記述・拡張したツールであると言えます。
Railsアプリケーションにおいて自動化したいケースとしては、「大量データに対する集計・統計処理」、「logファイルの定期的な削除」、「非同期で処理すべきタスクの実行(例えば、指定時刻にメール送信)」等が挙げられるでしょうか。 ここで述べたような要件がある場合には、「Whenever」の導入を検討するのもよいでしょう。
それでは早速「Whenever」の使い方を見てゆきましょう。 なお、今回の動作確認環境は以下の通りです。
まずは新規のRailsアプリケーションを作成します。 私は「whenever_sample」という名称にしました。
$ cd ~/work
$ rails new whenever_sample
次に、「Whenever」を使えるようにするため、Gemファイルに以下を追記します。
[Gemfile]
(初期設定されているgemの後ろに次を追加)
gem 'whenever', require: false
bundle install を実行します。
$ bundle install
...
Installing whenever 0.9.4
...
「Whenever」のインストールに成功しました。 現在のバージョンは 0.9.4 のようです。
ジョブの登録は config/schedule.rb に対して行います。 ファイルの生成には次のコマンドを利用します。
$ wheneverize .
[add] writing './config/schedule.rb'
[done] wheneverized!
schedule.rb ファイルが生成されました。
生成されたconfig/schedule.rb にはいくつかの例が挙げられています。 初めにこれを読み解きながら、使い方を見てみます。
[config/schedule.rb]
# Example: # # set :output, "/path/to/my/cron_log.log" ...(1) # # every 2.hours do ...(2) # command "/usr/bin/some_great_command" # runner "MyModel.some_method" # rake "some:great:rake:task" # end # # every 4.days do ...(3) # runner "AnotherModel.prune_old_records" # end
(1) の「set :output」ではログファイルの出力先を指定します。 例えば、次のように指定することでRailsの標準的なログファイルの位置に出力されます。 今回は筆者の作成したプロジェクトの位置を含むパスを指定します。
set :output, '/home/ti/work/whenever_sample/log/cron.log'
これで 'log' ディレクトリ以下にwheneverのログが書きだされるようになります。
(2) では「every 2.hours do ... end」の記述により2時間毎にジョブを実行するように指定しています。 実際のジョブの内容はメソッド呼出しのブロックに与えます。 ブロック内では利用したいものに応じて以下のような記述を加えます。
『command』
sh 等のOS上のコマンドを実行したい場合に利用します。
引数にはコマンドを渡します。 フルパスで指定する方が後々安心でしょう。
『runner』
モデルに定義されたメソッドを呼び出したい場合に使用します。
引数には「モデル名」と「メソッド名」をドットで連結した文字列を渡します。
『rake』
その名の通り、実行させたい rake コマンドを指定します。
複数のコマンドがありますが、使い分けの判断に迷うようでしたらとりあえず以下のような基準で考えてみてはいかがでしょうか。
(3) では「every 4.days do ... end」の記述により4日毎にジョブを実行するように指定しています。 この例のように、プログラムの意味するところがプログラマにとって非常に解りやすい(読みやすい)のが Rubyとその文化の良いところですよね。
ここでジョブの実行時間の指定方法についてまとめておきます。
先ほどまでの例で見てきた 「2.hours」, 「4.days」 等の指定に加え、以下のような指定も利用できます。
[config/schedule.rb]
# (1) 実行間隔の指定 # # 一時間毎に実行する every :hour do #他にも :day, :month, :year, :reboot 等が利用可 runner "ViewRanking.sum_up" end
「特定の曜日に実行したい」、あるいは「週末にのみ実行したい」といった場合には次のように指定できます。
[config/schedule.rb]
# (2) 実行日の指定 # # 金曜日に実行する every :friday do #他にも :sunday や :weekday, :weekend 等 runner "Report.send_summary_mail" end
実行される時刻まで指定したい場合には次のように記述します。
[config/schedule.rb]
# (3) 実行時刻の指定
#
# 毎日"3:00"に実行する
every :day, at: "3:00 am" do"
runner "Task.count"
end
crontabの形式で直接指定することも可能です。
[config/schedule.rb]
# (4) crontab形式での指定
#
# 左から「分」「時」「日」「月」「曜日」
every '0 0 10-31 * *' do
runner "ComplecatedTask.count"
end
もしかすると、「生のcrontab形式で指定するのなら、crontabコマンドを使って直接編集しても構わないのでは?」と思われるかもしれません。 しかし、config/schedule.rb にまとめて宣言しておくことで「このアプリケーションが必要としているジョブはどれなのか」を明示できます。 また、別のサーバへの適用も楽になります。
それほど複雑なケースでなければ crontab形式以外の記述を採用すべきでしょう。 圧倒的に可読性が向上します。
さて、ここまでの記述が正しいものかチェックしましょう。 「whenever」 コマンドを実行します。 コマンドの実行はアプリケーション・ディレクトリの直下で行ってください。
$ whenever 0 * * * * /bin/bash -l -c "cd /home/ti/work/whenever_sample && bin/rails runner -e production "\""ViewRanking.sum_up"\""" 0 0 * * 5 /bin/bash -l -c "cd /home/ti/work/whenever_sample && bin/rails runner -e production "\""Report.send_summary_report"\""" 0 3 * * * /bin/bash -l -c "cd /home/ti/work/whenever_sample && bin/rails runner -e production "\""Task.count"\""" 0 0 10-31 * * /bin/bash -l -c "cd /home/ti/work/whenever_sample && bin/rails runner -e production "\""ComplecatedTask.count"\""" # [message] Above is your schedule file converted to cron syntax; your crontab file was not updated. # [message] Run `whenever --help" for more options.
先ほどまでに作成した4つのジョブがcrontab形式でどのようになるのか表示されます。 出力の最後の方(オレンジの部分)でも述べられていますが、この段階ではまだ crontabファイルは更新されていません。 (従って、ジョブは実行されません)
ジョブの登録には以下のコマンドを実行してください。
$ whenever --update-crontab
[write] crontab file updated
ここまでで作成してきたジョブがcrontabに反映されたようです。 実際のcrontabファイルを確認しましょう。 次のコマンドを実行します。
$ crontab -l
実行結果は省略しますが、「whenever」コマンドで表示した内容と同じジョブが登録されていることを確認できると思います。
なお、ジョブを取り消したい場合には「whenever -c 」コマンドが利用できます。
今回は「Whenever」を紹介しました。
「Whenever」の本家サイト(GitHubページ)には「Cron jobs in Ruby」とあります。 cronの利用が有効と思われるシチュエーションでは是非「Whenever」の活用をご検討下さい。
今回触れなかった点に「CapistranoとWheneverの連携」があります。 こちらについては (*1) や (*3) が参考になります。
それでは、Enjoy Ruby!
*1 :筆者がコンピュータ(プログラム)に対して最も"すごい!"と思っている点はヒトの代わりに作業をしてくれる点、すなわち「自動化」にあります。 皆さんの周りには、コンピュータに任せられるムダな手作業がまだ残ってはいませんか?
*2 : 「Whenever」https://github.com/javan/whenever
*3 : 参考にさせていただきした。
http://railscasts.com/episodes/164-cron-in-ruby?view=asciicast
*4 : 参考にさせていただきました。
http://morizyun.github.io/blog/whenever-gem-rails-ruby-capistrano/
[IT研修]注目キーワード Python UiPath(RPA) 最新技術動向 Microsoft Azure Docker Kubernetes