Ruby-on-rails Rails 的 cron 作业:最佳实践?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/285717/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
A cron job for rails: best practices?
提问by jes5199
What's the best way to run scheduled tasks in a Rails environment? Script/runner? Rake? I would like to run the task every few minutes.
在 Rails 环境中运行计划任务的最佳方式是什么?脚本/跑步者?耙?我想每隔几分钟运行一次任务。
采纳答案by tardate
I'm using the rake approach (as supported by heroku)
我正在使用 rake 方法(由heroku支持)
With a file called lib/tasks/cron.rake ..
使用名为 lib/tasks/cron.rake 的文件 ..
task :cron => :environment do
puts "Pulling new requests..."
EdiListener.process_new_messages
puts "done."
end
To execute from the command line, this is just "rake cron". This command can then be put on the operating system cron/task scheduler as desired.
要从命令行执行,这只是“rake cron”。然后可以根据需要将此命令放在操作系统 cron/任务调度程序上。
Updatethis is quite an old question and answer! Some new info:
更新这是一个相当古老的问题和答案!一些新信息:
- the heroku cron service I referenced has since been replaced by Heroku Scheduler
- for frequent tasks (esp. where you want to avoid the Rails environment startup cost) my preferred approach is to use system cron to call a script that will either (a) poke a secure/private webhook API to invoke the required task in the background or (b) directly enqueue a task on your queuing system of choice
- 我引用的 heroku cron 服务已被Heroku Scheduler取代
- 对于频繁的任务(尤其是您想要避免 Rails 环境启动成本的情况),我的首选方法是使用系统 cron 调用一个脚本,该脚本将 (a) 戳一个安全/私有的 webhook API 以在后台调用所需的任务或 (b) 直接将任务排入您选择的排队系统
回答by Jim Garvin
I've used the extremely popular Wheneveron projects that rely heavily on scheduled tasks, and it's great. It gives you a nice DSL to define your scheduled tasks instead of having to deal with crontab format. From the README:
我在严重依赖计划任务的项目中使用了非常流行的When,它很棒。它为您提供了一个很好的 DSL 来定义您的计划任务,而不必处理 crontab 格式。从自述文件:
Whenever is a Ruby gem that provides a clear syntax for writing and deploying cron jobs.
任何时候都是一个 Ruby gem,它为编写和部署 cron 作业提供了清晰的语法。
Example from the README:
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
回答by Pankhuri
In our project we first used whenever gem, but confronted some problems.
在我们的项目中我们第一次使用了every gem,但是遇到了一些问题。
We then switched to RUFUS SCHEDULERgem, which turned out to be very easy and reliable for scheduling tasks in Rails.
然后我们切换到RUFUS SCHEDULERgem,结果证明它对于在 Rails 中调度任务非常简单和可靠。
We have used it for sending weekly & daily mails, and even for running some periodic rake tasks or any method.
我们已经用它来发送每周和每天的邮件,甚至用于运行一些定期的 rake 任务或任何方法。
The code used in this is like:
这里使用的代码是这样的:
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
To learn more: https://github.com/jmettraux/rufus-scheduler
回答by Freakent
Assuming your tasks don't take too long to complete, just create a new controller with an action for each task. Implement the logic of the task as controller code, Then set up a cronjob at the OS level that uses wget to invoke the URL of this controller and action at the appropriate time intervals. The advantages of this method are you:
假设您的任务不会花费太长时间来完成,只需为每个任务创建一个带有操作的新控制器。将任务的逻辑实现为控制器代码,然后在 OS 级别设置一个 cronjob,它使用 wget 以适当的时间间隔调用此控制器的 URL 和操作。这种方法的优点是你:
- Have full access to all your Rails objects just as in a normal controller.
- Can develop and test just as you do normal actions.
- Can also invoke your tasks adhoc from a simple web page.
- Don't consume any more memory by firing up additional ruby/rails processes.
- 就像在普通控制器中一样,可以完全访问所有 Rails 对象。
- 可以像执行正常操作一样进行开发和测试。
- 还可以从一个简单的网页临时调用您的任务。
- 不要通过启动额外的 ruby/rails 进程来消耗更多内存。
回答by webmat
script/runner and rake tasks are perfectly fine to run as cron jobs.
script/runner 和 rake 任务完全可以作为 cron 作业运行。
Here's one very important thing you must remember when running cron jobs. They probably won't be called from the root directory of your app. This means all your requires for files (as opposed to libraries) should be done with the explicit path: e.g. File.dirname(__FILE__) + "/other_file". This also means you have to know how to explicitly call them from another directory :-)
在运行 cron 作业时,您必须记住一件非常重要的事情。它们可能不会从您的应用程序的根目录调用。这意味着您对文件(而不是库)的所有需求都应该使用显式路径完成:例如 File.dirname(__FILE__) + "/other_file"。这也意味着您必须知道如何从另一个目录显式调用它们:-)
Check if your code supports being run from another directory with
检查您的代码是否支持从另一个目录运行
# 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
Also, cron jobs probably don't run as you, so don't depend on any shortcut you put in .bashrc. But that's just a standard cron tip ;-)
此外,cron 作业可能不会像您一样运行,因此不要依赖您在 .bashrc 中放置的任何快捷方式。但这只是一个标准的 cron 提示;-)
回答by Abdo
The problem with whenever (and cron) is that it reloads the rails environment every time it's executed, which is a real problem when your tasks are frequent or have a lot of initialization work to do. I have had issues in production because of this and must warn you.
When(和 cron)的问题在于它每次执行时都会重新加载 rails 环境,当您的任务很频繁或有很多初始化工作要做时,这是一个真正的问题。因此,我在生产中遇到了问题,必须警告您。
Rufus scheduler does it for me ( https://github.com/jmettraux/rufus-scheduler)
Rufus 调度程序为我完成(https://github.com/jmettraux/rufus-scheduler)
When I have long jobs to run, I use it with delayed_job ( https://github.com/collectiveidea/delayed_job)
当我有很长的工作要运行时,我将它与 delay_job ( https://github.com/collectiveidea/delayed_job) 一起使用
I hope this helps!
我希望这有帮助!
回答by Tyler Morgan
I'm a big fan of resque/resque scheduler. You can not only run repeating cron-like tasks but also tasks at specific times. The downside is, it requires a Redis server.
我是resque/ resque scheduler 的忠实粉丝。您不仅可以运行重复的类似 cron 的任务,还可以在特定时间运行任务。缺点是,它需要一个 Redis 服务器。
回答by Alexander Paramonov
That is interesting no one mentioned the Sidetiq. It is nice addition if you already using Sidekiq.
有趣的是没有人提到Sidetiq。如果您已经在使用 Sidekiq,这是一个很好的补充。
Sidetiq provides a simple API for defining recurring workers for Sidekiq.
Sidetiq 提供了一个简单的 API 来定义 Sidekiq 的循环工作者。
Job will look like this:
作业将如下所示:
class MyWorker
include Sidekiq::Worker
include Sidetiq::Schedulable
recurrence { hourly.minute_of_hour(15, 45) }
def perform
# do stuff ...
end
end
回答by Luke Francl
Both will work fine. I usually use script/runner.
两者都会正常工作。我通常使用脚本/运行程序。
Here's an example:
下面是一个例子:
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
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
You can also write a pure-Ruby script to do this if you load the right config files to connect to your database.
如果您加载正确的配置文件以连接到数据库,您也可以编写纯 Ruby 脚本来执行此操作。
One thing to keep in mind if memory is precious is that script/runner (or a Rake task that depends on 'environment') will load the entire Rails environment. If you only need to insert some records into the database, this will use memory you don't really have to. If you write your own script, you can avoid this. I haven't actually needed to do this yet, but I am considering it.
如果内存很宝贵,要记住的一件事是脚本/运行程序(或依赖于“环境”的 Rake 任务)将加载整个 Rails 环境。如果您只需要向数据库中插入一些记录,这将使用您实际上并不需要的内存。如果您编写自己的脚本,则可以避免这种情况。我实际上还不需要这样做,但我正在考虑。

