web-dev-qa-db-ja.com

Railsのcronジョブ:ベストプラクティス?

Rails環境でスケジュールされたタスクを実行する最良の方法は何ですか?スクリプト/ランナー?干し草・落ち葉などをかき集めるための)くま手、(土をならすための)まぐわ?

294
jes5199

私は熊手アプローチを使用しています( herok でサポート)

Lib/tasks/cron.rakeというファイルがあります。

task :cron => :environment do
  puts "Pulling new requests..."
  EdiListener.process_new_messages
  puts "done."
end

コマンドラインから実行する場合、これは単なる「rake cron」です。このコマンドは、必要に応じてオペレーティングシステムのcron /タスクスケジューラに配置できます。

Updateこれはかなり古い質問と回答です!いくつかの新しい情報:

  • 私が参照したheroku cronサービスは、その後 Heroku Scheduler に置き換えられました
  • 頻繁なタスク(特にRails環境の起動コストを避けたい場合)の場合、システムcronを使用して(a)セキュア/プライベートwebhook APIを呼び出して呼び出すスクリプトを呼び出すことをお勧めしますバックグラウンドで必要なタスク、または(b)選択したキューイングシステムでタスクを直接キューに入れる
110
tardate

私は非常に人気のある Whenever をスケジュールされたタスクに大きく依存するプロジェクトで使用しましたが、それは素晴らしいことです。 crontab形式を処理する代わりに、スケジュールされたタスクを定義するための素敵なDSLを提供します。 READMEから:

Cronジョブを作成および展開するための明確な構文を提供するRuby gemである場合。

READMEの例:

every 3.hours do
  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
252
Jim Garvin

このプロジェクトでは、gemを最初に使用しましたが、いくつかの問題に直面しました。

次に、RUFUS SCHEDULERgemに切り替えました。これは、Railsでタスクをスケジュールするのに非常に簡単で信頼できることがわかりました。

毎週および毎日のメールの送信、さらに定期的なレーキタスクやメソッドの実行にも使用しました。

これで使用されるコードは次のようなものです。

    require 'rufus-scheduler'

    scheduler = Rufus::Scheduler.new

    scheduler.in '10d' do
      # do something in 10 days
    end

    scheduler.at '2030/12/12 23:30:00' do
      # do something at a given point in time
    end

    scheduler.every '3h' do
      # do something every 3 hours
    end

    scheduler.cron '5 0 * * *' do
      # do something every day, five minutes after midnight
      # (see "man 5 crontab" in your terminal)
    end

詳細: https://github.com/jmettraux/rufus-scheduler

17
Pankhuri

タスクの完了にそれほど時間がかからない場合、各タスクのアクションを含む新しいコントローラーを作成するだけです。タスクのロジックをコントローラーコードとして実装し、wgetを使用して適切な時間間隔でこのコントローラーのURLとアクションを呼び出すOSレベルでcronjobをセットアップします。この方法の利点は次のとおりです。

  1. 通常のコントローラーと同じように、すべてのRailsオブジェクトにフルアクセスできます。
  2. 通常のアクションと同じように開発およびテストできます。
  3. シンプルなWebページからアドホックタスクを呼び出すこともできます。
  4. 追加のRuby/Railsプロセスを起動して、メモリを消費しないでください。
16
Freakent

私は resque / resque scheduler の大ファンです。 cronのようなタスクを繰り返し実行できるだけでなく、特定の時間にタスクを実行することもできます。欠点は、Redisサーバーが必要です。

10
Tyler Morgan

いつでも(およびcronで)問題は、実行されるたびにRails環境をリロードすることです。これは、タスクが頻繁に行われるか、多くの初期化作業が必要な場合の本当の問題です。このため、本番環境で問題が発生したため、警告する必要があります。

Rufusスケジューラーが私のためにそれをします( https://github.com/jmettraux/rufus-scheduler

実行する時間が長いジョブがある場合、delayed_jobで使用します( https://github.com/collectiveidea/delayed_job

これがお役に立てば幸いです!

10
Abdo

興味深いのは、誰も Sidetiq に言及していないことです。既にSidekiqを使用している場合、それは素晴らしい追加です。

Sidetiqは、Sidekiqの繰り返しワーカーを定義するためのシンプルなAPIを提供します。

ジョブは次のようになります。

class MyWorker
  include Sidekiq::Worker
  include Sidetiq::Schedulable

  recurrence { hourly.minute_of_hour(15, 45) }

  def perform
    # do stuff ...
  end
end
9
AlexParamonov

script/runnerおよびrakeタスクは、cronジョブとして実行してもまったく問題ありません。

Cronジョブを実行するときに覚えておく必要がある非常に重要なことを1つ示します。おそらく、アプリのルートディレクトリから呼び出されることはありません。これは、(ライブラリではなく)ファイルに必要なものはすべて、明示的なパスで実行する必要があることを意味します。 File.dirname(__ FILE__)+ "/ other_file"。これはまた、別のディレクトリから明示的に呼び出す方法を知っている必要があることを意味します:-)

コードで別のディレクトリからの実行をサポートしているかどうかを確認します

# from ~
/path/to/Ruby /path/to/app/script/runner -e development "MyClass.class_method"
/path/to/Ruby /path/to/rake -f /path/to/app/Rakefile rake:task Rails_ENV=development

また、cronジョブはおそらくユーザーとして実行されないため、.bashrcに配置したショートカットに依存しないでください。しかし、それは単なる標準的なcronのヒントです;-)

9
webmat

両方とも正常に動作します。私は通常スクリプト/ランナーを使用します。

次に例を示します。

0 6 * * * cd /var/www/apps/your_app/current; ./script/runner --environment production 'EmailSubscription.send_email_subscriptions' >> /var/www/apps/your_app/shared/log/send_email_subscriptions.log 2>&1

データベースに接続するための適切な設定ファイルをロードする場合、これを行うためにpure-Rubyスクリプトを書くこともできます。

メモリが貴重な場合に留意すべきことの1つは、スクリプト/ランナー(または「環境」に依存するRakeタスク)がRails環境全体をロードすることです。データベースにいくつかのレコードのみを挿入する必要がある場合、実際に必要のないメモリを使用します。独自のスクリプトを作成する場合、これを回避できます。まだ実際にこれを行う必要はありませんが、検討しています。

8
Luke Francl

Craken (レイク中心のcronジョブ)を使用します

8

Backgroundrbを使用します。

http://backgroundrb.rubyforge.org/

これを使用して、スケジュールされたタスクと、通常のクライアント/サーバーの関係には時間がかかりすぎるタスクを実行します。

5
salt.racer

SidekiqまたはResqueを使用する方がはるかに堅牢なソリューションです。どちらも、ジョブの再試行、REDISロックによる排他性、監視、およびスケジューリングをサポートしています。

Resqueは死んだプロジェクト(積極的に保守されていない)であるため、Sidekiqはより優れた代替手段であることに注意してください。また、パフォーマンスも向上しています。Sidekiqは単一のマルチスレッドプロセスで複数のワーカーを実行し、Resqueは各ワーカーを個別のプロセスで実行します。

3
jaysqrd

私は最近、私が取り組んでいるプロジェクトのためにいくつかのcronジョブを作成しました。

GemClockworkは非常に役立つことがわかりました。

require 'clockwork'

module Clockwork
  every(10.seconds, 'frequent.job')
end

このgemを使用してバックグラウンドジョブをスケジュールすることもできます。ドキュメントと詳細なヘルプについては、 https://github.com/Rykian/clockwork を参照してください

3
Vipul Lawande

Cronタスクを設定する方法は次のとおりです。 SQLデータベースの毎日のバックアップ(rakeを使用)を作成するものと、月に1回キャッシュを期限切れにするものがあります。出力はすべてlog/cron_logファイルに記録されます。私のcrontabは次のようになります。

crontab -l # command to print all cron tasks
crontab -e # command to edit/add cron tasks

# Contents of crontab
0 1 * * * cd /home/lenart/izziv. whiskas.si/current; /bin/sh cron_tasks >> log/cron_log 2>&1
0 0 1 * * cd /home/lenart/izziv.whiskas.si/current; /usr/bin/env /usr/local/bin/Ruby script/runner -e production lib/monthly_cron.rb >> log/cron_log 2>&1

最初のcronタスクは、毎日のデータベースバックアップを作成します。 cron_tasksの内容は次のとおりです。

/usr/local/bin/rake db:backup Rails_ENV=production; date; echo "END OF OUTPUT ----";

2番目のタスクは後でセットアップされ、スクリプト/ランナーを使用して月に一度キャッシュを期限切れにします(lib/monthly_cron.rb):

#!/usr/local/bin/Ruby
# Expire challenge cache
Challenge.force_expire_cache
puts "Expired cache for Challenges (Challenge.force_expire_cache) #{Time.now}"

他の方法でデータベースをバックアップできると思いますが、今のところはうまくいきます:)

paths to rakeおよびRubyは、サーバーによって異なる場合があります。以下を使用して、それらの場所を確認できます。

whereis Ruby # -> Ruby: /usr/local/bin/Ruby
whereis rake # -> rake: /usr/local/bin/rake
3
Lenart

かつて私は同じ決定をしなければならなかったし、今日、その決定に本当に満足している。 resque schedulerを使用します。これは、個別のredisがデータベースから負荷を取り除くだけでなく、優れたユーザーインターフェイスを提供するresque-webなどの多くのプラグインにもアクセスできるためです。システムが開発するにつれて、スケジュールするタスクが増え、1つの場所からそれらを制御できるようになります。

2
Caner Çakmak

resqueresque-schedular gemを使用してcronを作成できます。これは非常に簡単です。

https://github.com/resque/resque

https://github.com/resque/resque-scheduler

2
Israel Barba

clockwork gemを使用しました。スクリプトをデーモンとして実行できるclockworkd gemもあります。

1
nnattawat

おそらくそれを行うための最良の方法は、rakeを使用して必要なタスクを記述し、コマンドラインから実行することです。

非常に役立つ railscastsのビデオ を見ることができます。

この他のリソースもご覧ください。

1
Adrià Cidre

よくわからない、それはタスクに依存すると思う:実行する頻度、どれだけ複雑で、Railsプロジェクトとの直接通信が必要かなど。ただ "One Best Way"何かをするために、それほど多くの異なる方法はありません。

Railsプロジェクトの最後の仕事で、サーバーに時間があればいつでも計画されたメールを送信するバッチ招待メーラー(スパムではなく、調査招待)を作成する必要がありました。 daemon tools を使用して、作成したrakeタスクを実行するつもりだったと思います。

残念ながら、私たちの会社にはいくつかのお金の問題があり、メインのライバルに「買われた」ので、プロジェクトは完了しなかったので、最終的に何を使用したかわかりません。

0

スクリプトを使用してcronを実行します。これはcronを実行する最良の方法です。 cronの例を次に示します。

CronTabを開く—> Sudo crontab -e

そして、ベローズの線を貼り付けます:

00 00 * * * wget https:// your_Host/some_API_end_point

ここにいくつかのcron形式があり、あなたを助けます

::CRON FORMAT::

cron format table

Examples Of crontab Entries
15 6 2 1 * /home/melissa/backup.sh
Run the Shell script /home/melissa/backup.sh on January 2 at 6:15 A.M.

15 06 02 Jan * /home/melissa/backup.sh
Same as the above entry. Zeroes can be added at the beginning of a number for legibility, without changing their value.

0 9-18 * * * /home/carl/hourly-archive.sh
Run /home/carl/hourly-archive.sh every hour, on the hour, from 9 A.M. through 6 P.M., every day.

0 9,18 * * Mon /home/wendy/script.sh
Run /home/wendy/script.sh every Monday, at 9 A.M. and 6 P.M.

30 22 * * Mon,Tue,Wed,Thu,Fri /usr/local/bin/backup
Run /usr/local/bin/backup at 10:30 P.M., every weekday. 

これがあなたを助けることを願っています:)

0
Ami