Задача cron для рельсов: лучшие практики?

Каков наилучший способ запуска запланированных задач в среде Rails? Сценарий/бегун? Грабли? Я хотел бы запускать задачу каждые несколько минут.

Ответ 1

Я использую подход рейка (поддерживаемый 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
  • для частых задач (особенно в тех случаях, когда вы хотите избежать затрат на запуск среды Rails), мой предпочтительный подход - использовать системный cron для вызова script, который либо (a) будет вызывать защищенный/закрытый API веб-хостов для вызова требуемая задача в фоновом режиме или (b) непосредственно поставить в очередь задачу в выбранной вашей системе ожидания

Ответ 2

Я использовал чрезвычайно популярный Whenever для проектов, которые в значительной степени зависят от запланированных задач, и это здорово. Это дает вам хороший DSL для определения ваших запланированных задач вместо того, чтобы иметь дело с форматом crontab. Из README:

Всякий раз, когда это драгоценный камень Ruby, который обеспечивает четкий синтаксис для написания и развертывания cron jobs.

Пример из 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

Ответ 3

В нашем проекте мы впервые использовали всякий раз, когда были жемчужины, но столкнулись с некоторыми проблемами.

Затем мы переключились на RUFUS SCHEDULER, который оказался очень простым и надежным для планирования задач в Rails.

Мы использовали его для отправки еженедельных и ежедневных писем и даже для выполнения некоторых периодических задач рейка или любого метода.

Используемый здесь код выглядит следующим образом:

    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

Предполагая, что ваши задачи не занимают слишком много времени, просто создайте новый контроллер с действием для каждой задачи. Реализуйте логику задачи как код контроллера. Затем настройте cronjob на уровне ОС, который использует wget для вызова URL-адреса этого контроллера и действия с соответствующими временными интервалами. Преимущества этого метода:

  • Полный доступ ко всем объектам Rails, как и к обычным контроллерам.
  • Может развиваться и тестироваться так же, как вы делаете обычные действия.
  • Можно также вызвать ваши задачи adhoc с простой веб-страницы.
  • Не потребляйте больше памяти, запуская дополнительные процессы ruby ​​/rails.

Ответ 5

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; -)

Ответ 6

Проблема с когда (и cron) заключается в том, что она перезагружает среду рельсов каждый раз, когда она выполняется, что является реальной проблемой, когда ваши задачи часты или много работы по инициализации. Из-за этого у меня были проблемы с производством, и вы должны предупредить вас.

Rufus scheduler делает это для меня (https://github.com/jmettraux/rufus-scheduler)

Когда у меня есть длинные задания для запуска, я использую его с задержкой_job (https://github.com/collectiveidea/delayed_job)

Надеюсь, это поможет!

Ответ 7

Я большой поклонник resque/планировщик resque. Вы можете не только выполнять повторяющиеся задачи, подобные cron, но и задачи в определенное время. Недостатком является то, что для него требуется сервер Redis.

Ответ 8

Интересно, что никто не упоминал 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

Ответ 9

Оба будут работать нормально. Обычно я использую script/runner.

Вот пример:

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

Вы также можете записать pure-Ruby script, если вы загрузите нужные файлы конфигурации для подключения к своей базе данных.

Следует помнить, что память важна тем, что script/runner (или задача Rake, зависящая от "среды" ) загрузит всю среду Rails. Если вам нужно только вставить некоторые записи в базу данных, это будет использовать память, на которой вам действительно не нужно. Если вы напишете свой собственный script, вы можете избежать этого. Мне на самом деле не нужно было этого делать, но я рассматриваю это.

Ответ 10

Используйте Craken (задания с грабежами cron)

Ответ 11

Я использую backgroundrb.

http://backgroundrb.rubyforge.org/

Я использую его для запуска запланированных задач, а также задач, которые слишком долго подходят для нормальных отношений клиент/сервер.

Ответ 12

Вот как я установил свои задачи 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 делает ежедневные резервные копии db. Содержимое cron_tasks выглядит следующим образом:

/usr/local/bin/rake db:backup RAILS_ENV=production; date; echo "END OF OUTPUT ----";

Вторая задача была установлена ​​позже и использует script/runner для истечения кеша один раз в месяц (lib/month_cron.rb):

#!/usr/local/bin/ruby
# Expire challenge cache
Challenge.force_expire_cache
puts "Expired cache for Challenges (Challenge.force_expire_cache) #{Time.now}"

Думаю, я мог бы сделать резервную копию базы данных по-другому, но пока это работает для меня:)

пути для грабли и рубины могут различаться на разных серверах. Вы можете увидеть, где они находятся:

whereis ruby # -> ruby: /usr/local/bin/ruby
whereis rake # -> rake: /usr/local/bin/rake

Ответ 13

Использование чего-то Sidekiq или Resque - гораздо более надежное решение. Они поддерживают повторную работу, исключительность с блокировкой REDIS, мониторинг и планирование.

Имейте в виду, что Resque - это мертвый проект (не активно поддерживается), поэтому Sidekiq - лучшая альтернатива. Он также более эффективен: Sidekiq запускает нескольких рабочих в одном многопоточном процессе, а Resque запускает каждого рабочего в отдельном процессе.

Ответ 14

Недавно я создал несколько заданий cron для проектов, над которыми я работал.

Я обнаружил, что драгоценный камень Clockwork очень полезен.

require 'clockwork'

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

Вы можете даже планировать свою фоновое задание с помощью этого драгоценного камня. Для документации и дальнейшей помощи обратитесь https://github.com/Rykian/clockwork

Ответ 15

Как только я должен был принять такое же решение, и сегодня я действительно доволен этим решением. Используйте планировщик resque, потому что не только отдельный redis выведет нагрузку с вашего db, вы также получите доступ ко многим плагинам, таким как resque-web, который обеспечивает отличный пользовательский интерфейс. По мере развития вашей системы у вас будет все больше задач для планирования, чтобы вы могли контролировать их из одного места.

Ответ 17

Вероятно, лучший способ сделать это - использовать rake для записи требуемых задач и просто выполнить его через командную строку.

Вы можете увидеть очень полезное видео в railscasts

Также рассмотрим другие ресурсы:

Ответ 18

Я использовал clockwork gem, и это работает очень хорошо для меня. Существует также clockworkd gem, который позволяет script запускаться как демон.

Ответ 19

Я не уверен, я думаю, это зависит от задачи: как часто запускать, насколько сложно и насколько нужна прямая связь с проектом рельсов и т.д. Я думаю, если бы был только один "Один лучший способ", чтобы сделать что-то, не было бы так много разных способов сделать это.

На моей последней работе в проекте Rails нам нужно было создать почтовую рассылку приглашений (приглашения на просмотр, а не рассылку спама), которые должны отправлять запланированные письма всякий раз, когда у сервера было время. Я думаю, что мы будем использовать инструменты daemon для запуска созданных мной задач грабли.

К сожалению, у нашей компании были проблемы с деньгами и был "куплен" главным конкурентом, поэтому проект так и не был завершен, поэтому я не знаю, что мы в конечном итоге использовали.

Ответ 20

Я использую script для запуска cron, это лучший способ запуска cron. Вот пример для cron,

Открыть CronTab → sudo crontab -e

И вставить строки Bellow:

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. 

Надеюсь, это поможет вам:)