提问



在Rails环境中运行预定任务的最佳方法是什么?脚本/跑步者?耙?

最佳参考


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


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


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


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


更新这是一个很老的问答!一些新信息:



  • 我引用的heroku cron服务已被Heroku Scheduler取代

  • 对于频繁的任务(尤其是你想要避免Rails环境启动成本的地方)我首选的方法是使用system cron调用一个脚本,该脚本将(a)戳一个安全/私有webhook API来调用所需的任务在后台或(b)直接将任务排在您选择的排队系统上


其它参考1


我曾经非常热衷于那些严重依赖预定任务的项目,而且非常棒。它为您提供了一个很好的DSL来定义您的计划任务,而不必处理crontab格式。来自自述文件:[16] [17]



  每当Ruby宝石提供一个
  清晰的编写和部署语法
  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

其它参考2


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



  1. 完全访问所有Rails对象,就像在普通控制器中一样。

  2. 可以像正常行动一样进行开发和测试。

  3. 还可以从简单的网页调用您的任务。

  4. 不要通过启动额外的ruby/rails进程来消耗更多内存。


其它参考3


在我们的项目中,我们首先使用gem,但遇到了一些问题。


然后我们切换到 RUFUS SCHEDULER gem,结果证明在Rails中调度任务非常容易和可靠。[18]


我们用它来发送每周和每周每日邮件,甚至用于运行一些定期的佣金任务或任何方法。


这里使用的代码如下:


    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 [[]]]]

其它参考4


每次(和cron)的问题是它每次执行时都会重新加载rails环境,这在你的任务频繁或需要进行大量初始化工作时才是真正的问题。我在生产中遇到了问题,因为这一点,必须警告你。


Rufus调度程序为我做(https://github.com/jmettraux/rufus-scheduler)[20]


当我有很长的工作要运行时,我将它用于delayed_job(https://github.com/collectiveidea/delayed_job)[21]


我希望这有帮助!

其它参考5


我是resque/resque调度程序的忠实粉丝。你不仅可以在特定时间运行重复的类似cron的任务,还可以运行任务。缺点是,它需要Redis服务器。[22] [23]

其它参考6


脚本/跑步者和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提示;-)

其它参考7


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


这是一个例子:


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环境。如果你只需要在数据库中插入一些记录,这将使用你真正不需要的内存。如果你编写自己的脚本,你可以避免这种情况。我还没有真正需要这样做,但我是考虑一下。

其它参考8


使用Craken(rake centric cron jobs)[24]

其它参考9


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



  Sidetiq提供了一个简单的API来定义重复工作者
  Sidekiq。



工作将如下所示:


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

  recurrence { hourly.minute_of_hour(15, 45) }

  def perform
    # do stuff ...
  end
end

其它参考10


我用backgroundrb。


http://backgroundrb.rubyforge.org/[26]


我使用它来运行计划任务以及对于正常客户端/服务器关系花费太长时间的任务。

其它参考11


这是我如何设置我的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

其它参考12


使用Sidekiq或Resque是一种更强大的解决方案。它们都支持重试作业,具有REDIS锁定的独占性,监控和日程安排。


请记住,Resque是一个死的项目(没有积极维护),所以Sidekiq是一种更好的选择。它也更高效:Sidekiq在单个多线程进程中运行多个worker,而Resque在一个单独的进程中运行每个worker。

其它参考13


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


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


require 'clockwork'

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


您甚至可以使用此gem安排后台作业。
有关文档和进一步的帮助,请参阅https://github.com/Rykian/clockwork [27]

其它参考14


一旦我必须做出同样的决定,我今天对这个决定感到非常满意。使用 resque scheduler ,因为不仅单独的redis会从你的数据库中取出负载,你也可以访问许多插件,如resque-web,提供了一个很好的用户界面。随着你的系统开发,你将有越来越多的任务安排,所以你将能够从一个地方控制它们。

其它参考15


你可以使用resque和resque-shheduler gem来创建crons,这很容易做到。


https://github.com/resque/resque[28]


https://github.com/resque/resque-scheduler[29]

其它参考16


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


你可以在railscasts上看到一个非常有用的视频[30]


另请查看其他资源:



  • Rails Rake Tutorial


其它参考17


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

其它参考18


我不太确定,我想这取决于任务:运行频率,复杂程度以及与rails项目的直接通信需要多少等等。我想如果只有One Best Way 做某事,没有太多不同的方法可以做到。


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


不幸的是,我们公司遇到了一些资金问题并被主要竞争对手买走,所以项目从未完成,所以我不知道最终会用到什么。

其它参考19


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


打开CronTab - > sudo crontab -e


并粘贴Bellow线:


00 00 * * * wget https://your_host/some_API_end_point [34]


这里有一些cron格式,会对你有所帮助


::CRON FORMAT::


[35]


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. 


希望对你有帮助 :)