Rakeタスクとcronの設定

Rakeタスクとcronの設定

[Rakeについて]
Rakeは、rubyで特定の処理を定義できるツールです。
Rakeが実行する処理内容を「Rakeタスク」と呼び、「Rakefile」に記述します。

[cronについて]
cron(クーロン)と呼ばれる仕組みは、UNIX系のOSに標準で備わっている。
「○時になったら○○のコマンドを実行」などといった具合に、定期的にコマンドを実行するためにメモリ場で常に命令を待機しているプロセス(=デーモンプロセス)。
アプリケーションを起動せずにターミナル上で処理を実行できる

cronに対して設定を行うには、crontabコマンドを実行する(以下に一例を示します)

現在設定されている定時実行のタスクの一覧を表示
crontab -l

cronを削除
crontab -r

cronを編集
crontab -e cronを編集する時は、編集の[-e]オプションと削除の[-r]オプションがキーボードで隣り合わせなので、打ち間違えないように注意!!(オススメのやり方があるので、下記参考記事を参照)
crontabコマンドの使い方: UNIX/Linuxの部屋

[whenever Gemについて]
cronの設定を、rubyの簡単な文法で扱えるようにしたGem

[Rakeタスクを作成してcronに登録する流れ]
Rakeタスクを記述してcronに設定する流れは、以下になります

以下コマンドでrakeタスクのファイルを作成

$ rails g task (生成するrakeタスクのファイル名)


作成したrakeファイルに以下のように記述する

[lib/tasks ファイル]

namespace :state_update do    # 名前空間
  desc "記事のstateの更新"      # タスクの説明(descriptionの事)
  task update: :environment do      # タスクの名前(モデルにアクセスしてDBを操作する場合は、:enviromentを付ける)
    Article.publish_wait.past_published.find_each(&:published!)       # 実行したい処理
  end
end


上記で設定したタスクが現在のアプリに登録されているかを確認するには以下のコマンドで確認できる

$ rails -T


設定したrakeタスクは、ターミナル上で下記コマンドで実行できる

$ rails (名前空間名):(タスクの名前)
# 今回の場合は、[rails state_update:update]


作成したrakeタスクを自動で決まった時間で動作させる為には、cronに設定する必要がある
cronへの設定は、記述方法が難しかったりするのでruby形式で記述して、それをcronに設定してくれる[whenever]Gemを使う
[whenever]Gemは、cronの記述方法に翻訳してくれて、それをcronに反映させてくれる
ここからは、[whenever]Gemの使い方になります
Gemfileに以下のように記述する

gem 'whenever', require: false


以下を実行すると実行タイミングとタスクを記述する[config/schedule.rb]が生成される

$ wheneverize .


生成された[config/schedule.rb]に以下のように記述する

[config/schedule.rb]

require File.expand_path(File.dirname(__FILE__) + '/environment')    #  Rails.rootを使用するために記述
rails_env = ENV['RAILS_ENV'] || :development     #   cronを実行する環境変数
set :environment, rails_env    #   cronを実行する環境変数をセット
set :output, "#{Rails.root}/log/cron2.log"    #    ログの出力先
job_type :rake,    "cd :path && :environment_variable=:environment bundle exec rake :task :output"  # rakeというjob_typeは、通常だと[--silent]オプションが付いており、ログファイルにログを出力できないので、rakeを再定義

every 1.hour do     # コマンドの実行頻度を記述
  rake "state_update:update"   #  rakeというのは、railsコマンドと=のrakeではなくwheneverに定義してあるrakeというjob_typeということ。[(job_type) "(rakeタスク実行時のコマンド)"]という形式になっている
end


下記コマンドでcronへrakeタスクを登録できる

$ whenever --update-crontab


[crontab -l]などでcrontabファイルの中を確認すると、以下のようになっている

# Begin Whenever generated tasks for: /Users/higmonta/workspace/runteq/application_tasks/2563_higmonta_runteq_curriculum_advanced/config/schedule.rb at: 2021-08-10 17:55:19 +0900
* * * * * /bin/bash -l -c 'eval "$(rbenv init -)"; cd /Users/higmonta/workspace/runteq/application_tasks/2563_higmonta_runteq_curriculum_advanced && RAILS_ENV=development bundle exec rake state_update:update >> /Users/higmonta/workspace/runteq/application_tasks/2563_higmonta_runteq_curriculum_advanced/log/cron2.log 2>&1'

[/bin/bash]と記述してあるのは、cronは現在ログインしているシェルとは別なシェルで動くため、使うシェルを指定している
$(rbenv init -)と記述があるのは、ログインしているシェルを通さないので、シェルに記載しているパスが通っていない為、rbenvが使えないので、rbenvを使えるようにrbenvを使うための記述

※ポイント
[config/schedule.rb]に記述するrakeは、railsコマンドと同義のrakeでななくrakeというjob_typeを指定するという意味のrake
rakeのjob_typeは、通常以下のようになっているが、これだと[--silent]オプションが付いており、ログファイルにログを出力できないので、[config/schedule.rb]にrakeのjob_typeを[--silent]を抜いて再定義する
"cd:path &&:environment_variable =:environment bundle exec rake:task --silent:output"
rakeなどの各job_typeは、GitHubを参照

参考記事:

Linux crontab command help and examples

crontabコマンドの使い方: UNIX/Linuxの部屋

Rakeタスクの実装 - Qiita

https://qiita.com/suzuki-koya/items/787b5562d2ae1a215d94

【Ruby on Rails】Rakeタスクの実装について解説します | たいらのエンジニアノート

wheneverを使ってcrontabにrakeタスクを設定する時に--silentオプションを外す方法 - Qiita

Railsでwheneverを使ってcronを設定する - Qiita