【rails】wheneverでcrontabが追記され続ける問題 | 瀬戸内の雲のように

【rails】wheneverでcrontabが追記され続ける問題

Posted: 2018-06-04


スポンサーリンク

目次

背景

railsでcronを扱うにはwheneverというgemを使う必要があります。これは非常に簡単に使えて便利なのですが、簡単故に意図通り動作せず困ってしまったので対応の内容をメモしておきたいと思います。

このブログはrailsで作られているのですが、sitemapの更新を定期的に行わせるためにwheneverを使っています。私の環境はcapistranoでデプロイしているので、デプロイ時にcronの更新を行うように設定しております。

 

環境

  • CentOS 7.4.1708
  • Rails 4.2.3
  • ruby 2.3.0p0
  • whenever (0.10.0)

 

事象

ある時、新しくプライバシーポリシーのページを追加しました。SEO対策のためsitemapを導入しているためsitemapの設定も編集し、/privacypolicyも含めるように変更しました。

そして次の日に再作成されたsitemapを確認したところ、/privacypolicyは入っていませんでした。

原因を調査したところ、crontabが以下のような状態になっており、deployの都度実行されるcrontabの設定がひたすら上書きされていた ということがわかりました。

#
# ↓同じタスクがリリースバージョン毎に実行される状態
#


# Begin Whenever generated tasks for: /var/www/simpleblog/releases/20180402234147/config/schedule.rb at: 2018-04-02 08:43:22 +0900
0 0 * * * /bin/bash -l -c 'cd /var/www/simpleblog/releases/20180402234147 && RAILS_ENV=production bundle exec rake sitemap:refresh --silent'


# End Whenever generated tasks for: /var/www/simpleblog/releases/20180402234147/config/schedule.rb at: 2018-04-02 08:43:22 +0900

# Begin Whenever generated tasks for: /var/www/simpleblog/releases/20180501234047/config/schedule.rb at: 2018-05-01 08:43:22 +0900
0 0 * * * /bin/bash -l -c 'cd /var/www/simpleblog/releases/20180501234047 && RAILS_ENV=production bundle exec rake sitemap:refresh --silent'


# End Whenever generated tasks for: /var/www/simpleblog/releases/20180501234047/config/schedule.rb at: 2018-05-01 08:43:22 +0900

# ~~中略~~

# Begin Whenever generated tasks for: /var/www/simpleblog/releases/20180604234247/config/schedule.rb at: 2018-06-05 08:43:22 +0900
0 0 * * * /bin/bash -l -c 'cd /var/www/simpleblog/releases/20180604234247 && RAILS_ENV=production bundle exec rake sitemap:refresh --silent'


# End Whenever generated tasks for: /var/www/simpleblog/releases/20180604234247/config/schedule.rb at: 2018-06-05 08:43:22 +0900

おそらく、これにより古いsitemapの設定と競合していたことが原因だと推測しました。

 

原因

capistranoの設定ファイル(deploy.rb)に設定していたwheneverの設定が間違っていました。
元々は以下のように設定していました。

# config/deploy.rb

# wheneverによるcrontabの設定
set :whenever_identifier, ->{ "#{fetch(:application)}_#{fetch(:stage)}" }

# ~~~~ 中略 ~~~

  desc 'set crontab'
  task :whenever do
    on roles(:app) do

      within release_path do
        execute :bundle, :exec, 'whenever --update-crontab' ## ★ココ
      end
    end
  end


# ~~~中略~~~

  # 実行
  after :deploy, 'deploy:whenever'

上記の、execute :bundle, :exec, 'whenever --update-crontab' という設定が問題でした。
これは crontabに追記する という意味なので、消されることなくどんどん追記されていってました。

 

対応の検討

案としては2つありました。

① 新しく追記する前に前回の設定を消す
② 追記ではなく上書きにする

きれいな対策は①だと考えたので、その方向で調べました。

すると、以下のような設定でできそうだということがわかりました。

  desc 'set crontab'
  task :whenever do
    on roles(:app) do
      ### ↓追記ここから
      within previous_release do
        execute :bundle, :exec, 'whenever --clear-crontab'
      end
      ### ↑追記ここまで

      within release_path do
        execute :bundle, :exec, 'whenever --update-crontab'
      end
    end
  end

wheneverには --clear-crontabというオプションがあり、前回のリリースパスに対して消せばうまくいくと考えました。

しかし、結果はエラーでした。

というのも、新しいバージョンのwheneverではprevious_release という変数が使えなくなっているとのこと。
また他の方法で前回のリリースパスを取得する方法も自分では見つけられず、仕方なく諦めることに。。

解決策

結局、②のように都度上書きする方法で対応することにしました。
これは--write-crontabというオプションで対応可能でした。

# config/deploy.rb

# wheneverによるcrontabの設定
set :whenever_identifier, ->{ "#{fetch(:application)}_#{fetch(:stage)}" }

# ~~~~ 中略 ~~~

  desc 'set crontab'
  task :whenever do
    on roles(:app) do

      within release_path do
        #execute :bundle, :exec, 'whenever --update-crontab'
        execute :bundle, :exec, 'whenever --write-crontab'
      end
    end
  end


# ~~~中略~~~

  # 実行
  after :deploy, 'deploy:whenever'

一応これで解決したのですが、他のcron設定も全て消えてしまうこと が難点です。
railsは奥深いです。


スポンサーリンク




コメント一覧


コメントを投稿する


お名前


コメント内容





TOP back