Rails環境でスケジュールされたタスクを実行する最良の方法は何ですか? スクリプト/ランナー? レーキ?数分ごとにタスクを実行したいと思います。
20 に答える
スケジュールされたタスクに大きく依存するプロジェクトでは、非常に人気のあるWheneverを使用しましたが、これはすばらしいことです。crontab形式を処理する代わりに、スケジュールされたタスクを定義するための優れたDSLを提供します。READMEから:
いつでも、cronジョブを記述してデプロイするための明確な構文を提供するRubygemです。
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
私はrakeアプローチを使用しています(herokuでサポートされているように)
lib/tasks/cron.rake というファイルで ..
task :cron => :environment do
puts "Pulling new requests..."
EdiListener.process_new_messages
puts "done."
end
コマンドラインから実行するには、これは単に「rake cron」です。このコマンドは、必要に応じてオペレーティング システムの cron/タスク スケジューラに配置できます。
これはかなり古い質問と回答です。新しい情報:
- 私が参照した heroku cron サービスは、Heroku Schedulerに置き換えられました。
- 頻繁なタスク (特に、Rails 環境の起動コストを回避したい場合) の場合、私の推奨するアプローチは、システム cron を使用してスクリプトを呼び出すことです。このスクリプトは、(a) 安全な/プライベート Webhook API を突いてバックグラウンドで必要なタスクを呼び出します。または(b)選択したキューイングシステムでタスクを直接キューに入れる
私たちのプロジェクトでは、最初はいつでも gem を使用しましたが、いくつかの問題に直面しました。
その後、 RUFUS SCHEDULER gemに切り替えました。これは、Rails でタスクをスケジューリングするのに非常に簡単で信頼できることがわかりました。
毎週および毎日のメールを送信するために使用し、定期的なrakeタスクやその他の方法を実行するためにも使用しました.
これで使用されるコードは次のようなものです。
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 をご覧ください。
タスクの完了にそれほど時間がかからないと仮定すると、各タスクのアクションを含む新しいコントローラーを作成するだけです。タスクのロジックをコントローラー コードとして実装します。次に、wget を使用してこのコントローラーの URL を呼び出し、適切な時間間隔でアクションを実行する cron ジョブを OS レベルでセットアップします。この方法の利点は次のとおりです。
- 通常のコントローラーと同様に、すべての Rails オブジェクトに完全にアクセスできます。
- 通常のアクションと同じように開発およびテストできます。
- 簡単な Web ページからアドホックにタスクを呼び出すこともできます。
- 追加の ruby/rails プロセスを起動して、これ以上メモリを消費しないでください。
when (および cron) の問題は、実行されるたびに Rails 環境をリロードすることです。これは、タスクが頻繁に行われたり、初期化作業が多い場合に深刻な問題となります。このため、本番環境で問題が発生したため、警告する必要があります。
Rufus スケジューラーがそれをやってくれます ( https://github.com/jmettraux/rufus-scheduler )
実行するジョブが長い場合は、delayed_job ( https://github.com/collectiveidea/delayed_job )と共に使用します。
これが役立つことを願っています!
script/runner および rake タスクは、cron ジョブとして実行してもまったく問題ありません。
cron ジョブを実行するときに覚えておく必要がある非常に重要なことが 1 つあります。おそらく、アプリのルート ディレクトリから呼び出されることはありません。これは、(ライブラリとは対照的に) ファイルに対するすべての require は、明示的なパスで行う必要があることを意味します: 例: 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 のヒントです ;-)
私はresque / resque schedulerの大ファンです。cron のようなタスクを繰り返し実行できるだけでなく、特定の時間にタスクを実行することもできます。欠点は、Redis サーバーが必要なことです。
どちらもうまくいきます。私は通常、スクリプト/ランナーを使用します。
次に例を示します。
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
データベースに接続するための適切な構成ファイルをロードする場合は、これを行うための純粋な Ruby スクリプトを作成することもできます。
メモリが貴重な場合に留意すべきことの 1 つは、スクリプト/ランナー (または「環境」に依存する Rake タスク) が Rails 環境全体をロードすることです。データベースにいくつかのレコードを挿入する必要があるだけの場合、実際には必要のないメモリが使用されます。独自のスクリプトを作成すると、これを回避できます。実際にはまだこれを行う必要はありませんが、検討しています。
Craken (rake 中心の cron ジョブ)を使用する
私はbackgroundrbを使用しています。
http://backgroundrb.rubyforge.org/
通常のクライアント/サーバー関係では時間がかかりすぎるタスクだけでなく、スケジュールされたタスクを実行するためにも使用します。
Sidekiq や Resque を使用すると、はるかに堅牢なソリューションになります。どちらも、ジョブの再試行、REDIS ロックによる排他性、監視、およびスケジューリングをサポートしています。
Resque は終了したプロジェクト (積極的にメンテナンスされていない) であるため、Sidekiq がより優れた代替手段であることに注意してください。また、パフォーマンスも向上しています。Sidekiq は単一のマルチスレッド プロセスで複数のワーカーを実行しますが、Resque は各ワーカーを個別のプロセスで実行します。
私は最近、取り組んできたプロジェクトのためにいくつかの cron ジョブを作成しました。
ジェムClockworkが非常に便利であることがわかりました。
require 'clockwork'
module Clockwork
every(10.seconds, 'frequent.job')
end
この gem を使用して、バックグラウンド ジョブをスケジュールすることもできます。ドキュメントと詳細なヘルプについては、https://github.com/Rykian/clockworkを参照してください。
cron タスクをセットアップする方法は次のとおりです。1 つは SQL データベースの毎日のバックアップ (rake を使用) を作成するもので、もう 1 つは月に 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 番目のタスクは後でセットアップされ、script/runner を使用して 1 か月に 1 回キャッシュを期限切れにします (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}"
他の方法でデータベースをバックアップできると思いますが、今のところうまくいきます:)
rake と ruby へのパスは、サーバーによって異なる場合があります。以下を使用して、それらがどこにあるかを確認できます。
whereis ruby # -> ruby: /usr/local/bin/ruby
whereis rake # -> rake: /usr/local/bin/rake
resque
cron の作成には gem を使用できますresque-schedular
。これは非常に簡単です。
かつて同じ決断を下さなければならなかったことがありますが、今日はその決断に本当に満足しています。個別の redis がデータベースから負荷を取り除くだけでなく、優れたユーザー インターフェイスを提供する resque-web などの多くのプラグインにもアクセスできるため、resque スケジューラを使用します。システムが発展するにつれて、スケジュールするタスクがますます増えるため、それらを 1 か所から制御できるようになります。
おそらくこれを行う最善の方法は、rake を使用して必要なタスクを記述し、コマンド ラインから実行することです。
railscasts で非常に役立つビデオを見ることができます
この他のリソースもご覧ください。
私は時計仕掛けの宝石を使用しましたが、私にとってはかなりうまく機能します。clockworkd
スクリプトをデーモンとして実行できるようにする gemもあります。
よくわかりませんが、それはタスクによると思います。実行する頻度、複雑さ、Railsプロジェクトとの直接通信がどれだけ必要かなどです。、それを行うにはそれほど多くの異なる方法はありません。
Rails プロジェクトでの私の最後の仕事では、サーバーが時間があるときはいつでも計画されたメールを送信するバッチ招待メーラー (スパムではなく調査の招待状) を作成する必要がありました。デーモン ツールを使用して、作成した rake タスクを実行するつもりだったと思います。
残念ながら、私たちの会社はいくつかのお金の問題を抱えていて、主要なライバルに「買収」されたため、プロジェクトは決して完了しませんでした。
スクリプトを使用して cron を実行します。これが cron を実行する最良の方法です。以下は、cron の例です。
CronTab を開く —> sudo crontab -e
次の行を貼り付けます。
00 00 * * * wget https://your_host/some_API_end_point
ここにいくつかのcronフォーマットがあります、あなたを助けるでしょう
::CRON FORMAT::
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.
これがあなたを助けることを願っています:)