おぴよの気まぐれ日記

おぴよの気まぐれ日記

岡山やプログラミング、ファッションのこと、子育てや人生、生き方についての備忘録。

【Ruby on Rails】決まった時間に自動で処理してくれる`whenever`の使い方!

こんばんは。早くエンジニアになりたいopiyoです。

以前rssを取得する方法について、まとめて見たのですが今日はそれの発展させたいと思います。 opiyotan.hatenablog.com

時代は変わる。そして情報も常に変わる。

だから、rss情報も常に最新の情報を自動で取得したいですよね。

そんな時に便利なのが自動で決まった時間に処理をしてくれるwheneverというgemです。

  • 毎日2時間毎にrss情報を取得する!
  • 毎日朝3時にDBのバックアップを取得する!

みたいな事が出来ちゃう訳ですね。

wheneverの導入

先ずは、wheneverという定期実行するためのgemをインストールします。

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

そして、魔法のbundle install

$ bundle install

次にやるのが、wheneverの設定を記述するファイルを作成します。 これはコマンドが用意されています。

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

すると、schedule.rbというファイルが出来上がります!

# 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

ここに定期実行する為の処理を書いていきますよー

schedule.rbの書き方

今回は、動作確認までしたいので1分毎にHelloWorldを出力するrakeタスクを呼び出す処理を設定します。

# config/schedule.rb
# cronログを吐き出す場所
set :output, File.join(Whenever.path, "log", "cron.log")
# ジョブの実行環境の指定
set :environment, :development

# 1分毎に`HelloWorld`を出力する
every 1.minutes do
  begin
    rake "rss:hello"
  rescue => e
    raise e
  end
end
# lib/tasks/rss.rake
namespace :rss do
  task :hello => :environment do
    rss_hello = RssImport.new
    rss_hello.hello
  end
end
# lib/rss_import.rb
class RssImport
  def hello
    puts "HelloWorld"
  end
end

これで準備は完了です!

wheneverを実行する

先ずは、設定ファイルの記述にミスが無いかどうかチェック!

エラーになる

$ bundle exec whenever
bundler: failed to load command: whenever (/Users/taku/.rbenv/versions/2.4.1/bin/whenever)
NameError: undefined local variable or method `import' for #<Whenever::JobList:0x007fb7fba35330>

こんなエラーが出た時は、設定ファイルをもう一度見直してください。 私はrakeタスクを定義する場所を""で囲っていなかったので最初ずっとエラーになってました。

他の問題としては、rakeタスクを設定しているファイルが読めていない可能性があるのでschedule.rbの最初にrequire "/path/to/config/environment.rb"を定義してみてください。

成功する

成功すると、こんなメッセージが表示されます。

$ bundle exec whenever
* * * * * /bin/bash -l -c 'cd /Users/taku/rails/mapachannel && RAILS_ENV=development bundle exec rake rss:hello --silent >> /Users/taku/rails/mapachannel/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というXXに登録してあげます!

$ bundle exec whenever --update-crontab
[write] crontab file updated

正しく設定されているかどうかは、crontab -lコマンドでチェック出来ます!

$ crontab -l

# Begin Whenever generated tasks for: /Users/taku/rails/mapachannel/config/schedule.rb at: 2018-01-18 14:21:42 +0900
* * * * * /bin/bash -l -c 'cd /Users/taku/rails/mapachannel && RAILS_ENV=development bundle exec rake rss:hello --silent >> /Users/taku/rails/mapachannel/log/cron.log 2>&1'

# End Whenever generated tasks for: /Users/taku/rails/mapachannel/config/schedule.rb at: 2018-01-18 14:21:42 +0900

なんかどのサイトを確認方法はcrontab -eって書かれてるのだけど、-eにするとviが開くから良くないと思うのだけど。 間違えて-eしてしまった場合は慌てずに、esc + :q!で閉じれます!

間違えて設定してしまった場合は、これで

$ bundle exec whenever --clear-crontab

定期実行されているかチェック

最後に1分間毎にHelloWorldが呼ばれているかチェックします。

logを見て見ましょう!

$ tail -f log/cron.log
HelloWorld
・
・
・

tail -fとするとリアルタイムにログを見る事が出来ます。 1分間毎にHelloWorldが増えて表示されれば成功してますね。