铁路的cron工作:最佳实践?
在Rails环境中运行计划任务的最佳方式是什么? 脚本/亚军? 耙?
我正在使用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 scheduler上。
更新这是一个相当古老的问题和答案! 一些新的信息:
- 我引用的heroku cron服务已经被Heroku Scheduler取代
- 对于频繁的任务(尤其是你想避免Rails环境启动成本的地方),我首选的方法是使用system cron来调用一个脚本,该脚本将(a)戳一个安全/私有的webhook API来在后台调用所需的任务或者(b)直接排队在您select的排队系统上的任务
我已经使用了非常受欢迎的每当依赖计划任务的项目,这是很好的。 它给你一个很好的DSL来定义你的计划任务,而不必处理crontab格式。 从自述文件:
每当一个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
假设你的任务不需要太长的时间来完成,只需要为每个任务创build一个新的控制器。 以控制器代码实现任务的逻辑,然后在操作系统级别设置一个cronjob,它使用wget以适当的时间间隔调用该控制器的URL和动作。 这种方法的优点是你:
- 像正常的控制器一样,可以完全访问所有的Rails对象。
- 可以像开展正常行为一样进行开发和testing。
- 也可以从简单的网页中调用你的任务。
- 不要通过启动额外的ruby / rails进程来消耗更多的内存。
在我们的项目中,我们首先使用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
每当(和cron)的问题是每次执行时都会重新载入rails环境,当你的任务频繁或者有很多初始化工作要做时,这是一个真正的问题。 由于这个原因,我在生产中遇到了问题,必须提醒你。
Rufus调度程序为我做( https://github.com/jmettraux/rufus-scheduler )
当我有很长的工作要运行时,我用delayed_job( https://github.com/collectiveidea/delayed_job )
我希望这有帮助!
我是resque / resque scheduler的忠实粉丝。 你不仅可以运行重复类似cron的任务,而且可以在特定的时间执行任务。 缺点是,它需要一个Redis服务器。
脚本/ runner和rake任务是完全正常运行作为cron作业。
运行cron作业时,您必须记住一件非常重要的事情。 他们可能不会从您的应用程序的根目录中调用。 这意味着所有您需要的文件(而不是库)需要使用显式path来完成:例如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提示;-)
两者都可以正常工作。 我通常使用脚本/亚军。
这是一个例子:
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
如果你加载正确的configuration文件连接到你的数据库,你也可以编写一个纯粹的Ruby脚本来做到这一点。
有一件事要记住,如果内存是宝贵的,那么script / runner(或者依赖于'environment'的Rake任务)将加载整个Rails环境。 如果你只需要在数据库中插入一些logging,这将使用你不需要的内存。 如果你写自己的脚本,你可以避免这一点。 我还没有真的需要这样做,但我正在考虑这一点。
使用Craken (以耙为中心的cron作业)
这很有趣,没有人提到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
以下是我如何设置我的cron任务。 我有一个使SQL数据库每日备份(使用耙)和另一个到一个月一次caching。 任何输出都logging在文件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 ----";
第二个任务是稍后设置的,并使用脚本/运行器每个月一次到期caching(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}"
我想我可以用其他方式备份数据库,但到目前为止,它适用于我:)
耙和ruby的path可以在不同的服务器上有所不同。 你可以看到他们在哪里使用:
whereis ruby # -> ruby: /usr/local/bin/ruby whereis rake # -> rake: /usr/local/bin/rake
使用Sidekiq或Resque是一个更强大的解决scheme。 他们都支持重试工作,排他性与REDISlocking,监控和计划。
请记住,Resque是一个死的项目(没有积极维护),所以Sidekiq是一个更好的select。 它也是更高性能的:Sidekiq在单个multithreading进程中运行多个工作者,而Resque在单独的进程中运行每个工作者。
我最近为我一直在做的项目创build了一些cron作业。
我发现gem发条非常有用。
require 'clockwork' module Clockwork every(10.seconds, 'frequent.job') end
你甚至可以使用这个gem安排你的后台工作。 有关文档和进一步的帮助,请参阅https://github.com/tomykaira/clockwork
一旦我必须做出同样的决定,我对今天的决定感到非常高兴。 使用resque调度器,因为不仅一个单独的redis将从您的数据库中取出负载,您还将有权访问许多插件,如resque-web,它提供了一个很好的用户界面。 随着你的系统的发展,你将有更多的任务安排,所以你将能够从一个地方控制他们。
你可以使用resque和resque-shheduler gem创buildcron,这很容易做到。
可能最好的方法是使用rake写出你需要的任务,然后通过命令行执行它。
您可以在railscasts上看到非常有用的video
另外看看这个其他的资源:
- Rails Rake教程
我用发条gem,它对我来说工作得很好。 还有一个clockworkd
gem,允许脚本作为守护进程运行。
我不是很确定,我想这取决于任务:运行的频率,复杂程度以及与rails项目的直接交stream是多less等等。我猜如果只有“一个最好的方法”来做一些事情,不会有太多不同的方法来做到这一点。
在Rails项目的最后一个工作中,我们需要制作一个批量邀请邮件程序(调查邀请,而不是垃圾邮件),只要服务器有时间,就会发送计划的邮件。 我想我们将使用守护进程工具来运行我创build的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 AM 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 AM through 6 PM, every day. 0 9,18 * * Mon /home/wendy/script.sh Run /home/wendy/script.sh every Monday, at 9 AM and 6 PM 30 22 * * Mon,Tue,Wed,Thu,Fri /usr/local/bin/backup Run /usr/local/bin/backup at 10:30 PM, every weekday.
希望这会帮助你:)