305

在 Rails 环境中运行计划任务的最佳方式是什么?脚本/跑步者?耙?我想每隔几分钟运行一次任务。

4

20 回答 20

265

我在严重依赖计划任务的项目中使用了非常流行的每当,它很棒。它为您提供了一个很好的 DSL 来定义您的计划任务,而不必处理 crontab 格式。从自述文件:

When 是一个 Ruby gem,它为编写和部署 cron 作业提供了清晰的语法。

自述文件中的示例:

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
于 2011-06-16T20:01:28.603 回答
114

我正在使用 rake 方法(由heroku支持)

使用名为 lib/tasks/cron.rake 的文件 ..

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

要从命令行执行,这只是“rake cron”。然后可以根据需要将此命令放在操作系统 cron/task 调度程序上。

更新这是一个相当古老的问题和答案!一些新信息:

  • 我引用的 heroku cron 服务已被Heroku Scheduler取代
  • 对于频繁的任务(尤其是您想避免 Rails 环境启动成本的地方),我首选的方法是使用系统 cron 调用脚本,该脚本将(a)戳一个安全/私有 webhook API 以在后台调用所需的任务或 (b) 直接在您选择的排队系统中加入任务
于 2009-06-15T11:40:50.423 回答
22

在我们的项目中,我们首先使用了 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

于 2013-08-10T06:23:37.550 回答
20

假设您的任务不会花费太长时间来完成,只需为每个任务创建一个带有操作的新控制器。将任务的逻辑实现为控制器代码,然后在操作系统级别设置一个 cronjob,使用 wget 以适当的时间间隔调用此控制器的 URL 和操作。这种方法的优点是你:

  1. 就像在普通控制器中一样,可以完全访问所有 Rails 对象。
  2. 可以像您进行正常操作一样进行开发和测试。
  3. 还可以从一个简单的网页临时调用您的任务。
  4. 不要通过启动额外的 ruby​​/rails 进程来消耗更多的内存。
于 2008-11-12T23:56:38.153 回答
12

每当(和 cron)的问题是它每次执行时都会重新加载 rails 环境,当您的任务很频繁或有很多初始化工作要做时,这是一个真正的问题。因此,我在生产中遇到了问题,必须警告您。

Rufus 调度程序为我做这件事(https://github.com/jmettraux/rufus-scheduler

当我有很长的工作要运行时,我将它与 delay_job ( https://github.com/collectiveidea/delayed_job )一起使用

我希望这有帮助!

于 2013-02-21T22:04:17.857 回答
11

script/runner 和 rake 任务非常适合作为 cron 作业运行。

这是运行 cron 作业时必须记住的一件非常重要的事情。它们可能不会从您的应用程序的根目录中调用。这意味着您对文件(而不是库)的所有需求都应使用显式路径完成:例如 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 提示;-)

于 2008-11-13T14:43:53.347 回答
11

我是resque / resque scheduler的忠实粉丝。您不仅可以运行重复的类似 cron 的任务,还可以在特定时间运行任务。缺点是,它需要一个 Redis 服务器。

于 2013-06-11T04:43:25.447 回答
11

有趣的是,没有人提到Sidetiq。如果您已经在使用 Sidekiq,这是很好的补充。

Sidetiq 提供了一个简单的 API 来为 Sidekiq 定义循环工作者。

作业将如下所示:

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

  recurrence { hourly.minute_of_hour(15, 45) }

  def perform
    # do stuff ...
  end
end
于 2015-10-13T15:44:30.500 回答
9

两者都可以正常工作。我通常使用脚本/跑步者。

这是一个例子:

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 脚本来执行此操作。

如果内存很宝贵,要记住的一件事是脚本/运行程序(或依赖于“环境”的 Rake 任务)将加载整个 Rails 环境。如果您只需要在数据库中插入一些记录,这将使用您实际上不需要的内存。如果您编写自己的脚本,则可以避免这种情况。我实际上还不需要这样做,但我正在考虑。

于 2008-11-14T18:19:17.063 回答
9

使用Craken(以 rake 为中心的 cron 作业)

于 2008-12-28T21:11:22.933 回答
6

我使用背景。

http://backgroundrb.rubyforge.org/

我使用它来运行计划任务以及对于正常的客户端/服务器关系而言耗时过长的任务。

于 2008-11-13T00:12:04.080 回答
5

使用 Sidekiq 或 Resque 是更强大的解决方案。它们都支持重试作业、具有 REDIS 锁的排他性、监控和调度。

请记住,Resque 是一个死项目(没有积极维护),所以 Sidekiq 是一个更好的选择。它还具有更高的性能:Sidekiq 在单个多线程进程中运行多个工作者,而 Resque 在单独的进程中运行每个工作者。

于 2014-10-24T20:20:07.157 回答
4

这是我设置 cron 任务的方式。我有一个用于 SQL 数据库的每日备份(使用 rake),另一个用于每月一次过期缓存。任何输出都记录在文件 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 ----";

第二个任务是稍后设置的,并使用脚本/运行器每月一次过期缓存(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
于 2009-01-26T15:54:15.780 回答
4

您可以使用resqueresque-schedulargem 来创建 cron,这很容易做到。

https://github.com/resque/resque

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

于 2014-08-26T18:10:29.577 回答
4

我最近为我一直从事的项目创建了一些 cron 工作。

我发现宝石发条非常有用。

require 'clockwork'

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

你甚至可以使用这个 gem 来安排你的后台工作。有关文档和进一步帮助,请参阅https://github.com/Rykian/clockwork

于 2015-11-05T09:35:20.157 回答
3

曾经我不得不做出同样的决定,今天我对这个决定感到非常高兴。使用resque 调度器,因为不仅一个单独的 redis 会从你的数据库中取出负载,你还可以访问许多插件,比如 resque-web,它提供了一个很好的用户界面。随着系统的发展,您将有越来越多的任务要安排,因此您将能够从一个地方控制它们。

于 2014-04-01T20:07:14.527 回答
2

可能最好的方法是使用 rake 编写您需要的任务,然后通过命令行执行它。

您可以在 railscasts看到一个非常有用的视频

另请查看其他资源:

于 2013-02-14T20:17:35.890 回答
2

我使用了发条宝石,它对我来说效果很好。还有clockworkd允许脚本作为守护进程运行的 gem。

于 2014-07-03T02:33:28.420 回答
1

我不太确定,我想这取决于任务:运行频率、复杂程度以及需要与 Rails 项目进行多少直接通信等。我想是否只有“一种最佳方式”来做某事,不会有这么多不同的方法来做到这一点。

在我在 Rails 项目中的最后一份工作中,我们需要制作一个批量邀请邮件(调查邀请,而不是垃圾邮件),它应该在服务器有时间时发送计划的邮件。我想我们将使用守护程序工具来运行我创建的 rake 任务。

不幸的是,我们公司出现了一些资金问题,被主要竞争对手“收购”,因此项目从未完成,所以我不知道我们最终会用什么。

于 2008-11-13T08:11:20.727 回答
1

我使用脚本运行 cron,这是运行 cron 的最佳方式。这是 cron 的一些示例,

打开 CronTab —> sudo crontab -e

并粘贴波纹管线:

00 00 * * * wget https://your_host/some_API_end_point

这是一些cron格式,对您有帮助

::CRON FORMAT::

cron 格式表

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. 

希望对你有帮助 :)

于 2017-09-21T10:27:45.837 回答