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

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


person jes5199    schedule 12.11.2008    source источник
comment
Для тех, кто пришел сюда из Google, посмотрите за рамки принятого ответа, чтобы найти лучшие подходы.   -  person jrdioko    schedule 09.07.2011
comment
Ответ «всякий раз» кажется более разумным, чем принятый ответ, который является старым приемом.   -  person Rob    schedule 11.01.2013
comment
Также имейте в виду, что хотя бы один ответ предполагает, что у вас установлен определенный драгоценный камень.   -  person Tass    schedule 08.07.2013
comment
Здесь кратко излагаются некоторые (как я выяснил) передовые практики wisecashhq. ru / blog / writing-надежные-cron-jobs   -  person Thibaut Barrère    schedule 17.09.2014
comment
Во многих случаях задания cron - неприятный запах. Лучше напишите планировщик через sidekiq / resque (или другой фоновый рабочий) или напишите демон (менее функциональный и контролируемый). У Cron-заданий есть, по крайней мере, несколько плохих вещей: 1) блокировка для одного экземпляра - это боль; 2) мониторинг не может быть простым; 3) обработка исключений должна быть снова написана вручную; 4) непросто перезапустить; 5) все вышеперечисленные вопросы легко решаются фоновыми работниками.   -  person Dmitry Polushkin    schedule 12.03.2015
comment
Рейк = Рубиновая марка. Это чрезвычайно мощный инструмент. Я рекомендую посмотреть на нем Railscast Райана Бейтса - railscasts.com/episodes/66-custom- рейк-задания   -  person Yoni    schedule 09.06.2016


Ответы (20)


Я использую метод рейка (поддерживаемый heroku)

С файлом lib / tasks / cron.rake ..

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

Для выполнения из командной строки это просто rake cron. Затем эту команду можно поместить в планировщик cron / задач операционной системы по желанию.

Обновление, это довольно старый вопрос и ответ! Немного новой информации:

  • Служба heroku cron, на которую я ссылался, с тех пор заменена Heroku Scheduler
  • для частых задач (особенно, когда вы хотите избежать затрат на запуск среды Rails), я предпочитаю использовать системный cron для вызова сценария, который либо (а) запускает безопасный / частный API веб-перехватчика, чтобы вызвать требуемую задачу в фоновом режиме или (б) напрямую поставить задачу в очередь в выбранной вами системе очередей.
person tardate    schedule 15.06.2009
comment
Какой должна быть запись в cron в этом случае, чтобы ОС знала правильный путь к задаче rake? - person jrdioko; 09.07.2011
comment
NB: в наши дни я использую всякий раз (см. Ответ Джима Гарвина), но необработанная запись cron для запуска задачи rake будет примерно такой: 30 4 * * * / bin / bash -l -c 'cd / opt / railsapp && RAILS_ENV = cron грабли производства --silent ' - person tardate; 12.07.2011
comment
Как это вызвать с консоли? Я сделал load "#{Rails.root}/lib/tasks/cron.rake" и rake cron, но получил NameError: undefined локальную переменную или метод cron для main: Object - person B Seven; 22.07.2011
comment
Проблема с этим подходом - зависимость :environment. У нас есть очень тяжелое приложение Rails, которое долго запускается, наш Rake вызывается каждую минуту и ​​потребляет больше ресурсов, запуская среду Rails, которая выполняет задачу. Я бы хотел иметь уже запущенную среду Rails для вызова через cron, должно быть что-то среднее между подходом controller и средой rake один. - person fguillen; 17.01.2012
comment
Какова продолжительность этой задачи? Я использую условие if. Я хочу знать, насколько регулярно это выполняется. Я не могу найти никакой информации об этом на сайте heroku. - person Shubham Chaudhary; 10.02.2015
comment
@ShubhamChaudhary cron, на который я ссылался, некоторое время назад был заменен планировщиком heroku. см. devcenter.heroku.com/articles/scheduler - person tardate; 11.02.2015
comment
Мне просто очень любопытно, какая разница в производительности по сравнению с фоновыми жемчужинами, такими как отложенная работа или sidekiq. Я определенно вижу преимущества, когда вы хотите организовать большое количество фоновых задач, хотя - person dtc; 29.06.2015
comment
@dtc запускать rake через cron довольно расточительно, так как он должен каждый раз загружать среду rails. dj или sidekiq поддерживают работу экземпляра (ов). Поэтому я предпочитаю использовать cron, чтобы задеть веб-перехватчик, который поставит в очередь требуемое задание. Это легкий вес, и вы получаете преимущество использования cron в качестве планировщика и dj / sidekiq в качестве очереди заданий. - person tardate; 30.06.2015
comment
@tardate в порядке, но вы можете настроить задачи с граблями, не загружая всю среду. кроме этого, это было бы почти то же самое? к сожалению, я не смотрел sidekiq и не знаю, что cron делает внутри, поэтому пока могу только догадываться - person dtc; 01.07.2015

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

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

Пример из 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
person Jim Garvin    schedule 16.06.2011
comment
Если он запускается каждую минуту, среда будет каждый раз перезапускаться, что может быть дорогостоящим. Похоже, что github.com/ssoroka/scheduler_daemon избегает этого. - person lulalala; 20.10.2011
comment
+1 для сохранения конфигурации cron в вашей системе контроля версий - person brittohalloran; 22.11.2011
comment
Думаю, это лучшее решение. Если вы используете рельсы, думаю, лучше все писать в рельсах. При таком подходе вы также можете забыть о задаче cron при смене серверов, она перемещается вместе с приложением. - person Adrian Matteo; 18.05.2012
comment
Есть отличный Railscast о том, когда это действительно полезно (более старый бесплатная версия тоже вышла). - person aceofbassgreg; 11.04.2013
comment
@Tony, всякий раз, когда это в основном предметно-ориентированный язык для написания cron-заданий. Он компилируется в обычный синтаксис cron на вашем сервере rails, и cron выполняет указанные вами задания (обычно через rails runner). - person Greg; 21.10.2014

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

Затем мы перешли на гем 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

person Pankhuri    schedule 10.08.2013
comment
Вверх для rufus, поскольку я использовал его как для простых проектов ruby, так и для приложений с полным рельсом. - person Paulo Fidalgo; 15.10.2013
comment
Не могли бы вы немного подробнее рассказать о проблемах, с которыми вы столкнулись «Всегда»? - person Duke; 20.02.2016
comment
самый лучший ответ - person Darlan D.; 27.05.2019

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

  1. Получите полный доступ ко всем вашим объектам Rails, как в обычном контроллере.
  2. Может развиваться и тестироваться так же, как вы делаете обычные действия.
  3. Также может вызывать ваши задачи adhoc с простой веб-страницы.
  4. Не потребляйте больше памяти, запуская дополнительные процессы ruby ​​/ rails.
person Freakent    schedule 12.11.2008
comment
Как запретить другим доступ к этой задаче? Если задача берет процессор и вызывает его часто, это вызовет проблемы. - person sarunw; 12.12.2009
comment
Так же, как и с любым другим контроллером. Убедитесь, что вы реализовали какую-то безопасность - AuthLogic или restful_authentication, а затем добавьте управление ролями поверх этого с помощью acl9 или чего-то еще. Затем вы можете использовать свое приложение rails для обслуживания всех задач через спокойный интерфейс с безопасностью и прочим, как и любой другой веб-сервис. Это дает такие вещи, как: вы можете использовать свой домен для аутентификации и позволить пользователю сервера запускать задачи, запланированные в cron или запланированные задачи, если вы используете окна. Также это позволяет вам получить доступ к тем же вещам через скрипт / бегун, если вам нужно. Продолжение в следующем комментарии. - person konung; 12.03.2010
comment
Выбежал из комнаты наверху. Основным преимуществом для меня является то, что я единственный пользователь уровня администратора на своей работе, и я не использую непрограммистов / несистемных администраторов с root-доступом для выполнения определенных заданий. Эта настройка позволяет вам создать страницу в вашем приложении rails, где авторизованный пользователь (например, Office Manager или Inventory Manager) может входить в систему и запускать определенные задания, не предоставляя им доступа к скрипту / средству выполнения или заданию cron. И снова, если вы пойдете по этому пути, вы можете позже использовать какой-либо другой плагин или гем rails, например рабочий или фоновый (не запоминайте точные имена, см. Ruby-toolbox.com) - person konung; 12.03.2010
comment
Я знаю, что это было некоторое время назад, но это определенно не лучший способ выполнять задания cron. Зачем идти через веб-интерфейс, нарушая то, что он на самом деле представляет, когда существует множество других способов доступа к среде Rails? - person Matchu; 28.11.2010
comment
Одна из проблем заключается в том, что он блокирует экземпляр до завершения этого задания. Если у вас запущено 3 экземпляра и вы запускаете 3 задания одновременно, ваши 3 экземпляра будут заняты и никакие другие запросы не будут обслуживаться. - person Matt Todd; 02.02.2011
comment
Квалификация, предполагающая, что ваши задачи не требуют слишком много времени для выполнения, кажется ОГРОМНОЙ. Не лучше ли использовать более общий подход, и не только в тех случаях, когда задачи выполняются очень быстро? Таким образом, вы не будете постоянно переоценивать, нужно ли переписывать ту или иную задачу с использованием другого подхода. - person iconoclast; 15.04.2011
comment
Этот старый вопрос - лучший результат Google для rails cron. Этот ответ - далеко не лучший подход. Пожалуйста, просмотрите другие ответы для более разумных предложений. - person Jim Garvin; 16.06.2011
comment
Не лучший способ. У вас есть много других способов получить доступ к окружению Rails через задание cron без вызова службы REST. Рейк-подход, безусловно, лучше - person Shine; 26.06.2012
comment
Я занимаюсь этим некоторое время, и в какой-то момент это становится реальной помехой. Теперь переписываем задачи, чтобы использовать rake / cron; Синатра был вовлечен в излишне сложные дела. - person Avishai; 09.06.2013
comment
Пожалуйста, проголосуйте против этого ответа, чтобы он имел отрицательное значение! Тогда люди узнают, что это плохой метод: D - person Imme22009; 21.09.2013
comment
шесть лет спустя я решил принять другой ответ. - person jes5199; 17.06.2014
comment
Никогда не следует выполнять длительную обработку в HTTP-запросе. Это работает только для очень быстрых вещей. - person Thibaut Barrère; 17.09.2014
comment
Хотя я согласен с тем, что это не лучший подход, я не так радикально против, как кажется большинству людей. Пока вы помните о некоторых вещах (ограничьте время выполнения, убедитесь, что действие не может быть инициировано всеми), это по-прежнему отличный способ быстро запустить и запустить периодическую задачу. Для дальнейшего чтения я написал статья об этом. - person Michael Trojanek; 22.09.2015
comment
Мне это нравится, потому что его очень легко настроить (у меня была такая же идея), и вам не нужно изучать использование гема, просто cron + wget и готово. Но я должен признать, что он предназначен только для небольших целей интрасети, поэтому никаких рисков безопасности и проблем с синхронизацией. - person Martin T.; 21.11.2019

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

Планировщик Rufus сделает это за меня (https://github.com/jmettraux/rufus-scheduler)

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

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

person Abdo    schedule 21.02.2013

Задачи script / runner и rake отлично подходят для выполнения как задач cron.

Вот одна очень важная вещь, которую вы должны помнить при запуске заданий cron. Вероятно, они не будут вызываться из корневого каталога вашего приложения. Это означает, что все ваши требования к файлам (в отличие от библиотек) должны выполняться с явным путем: например. Имя_файла (__ 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 ;-)

person webmat    schedule 13.11.2008
comment
Вы можете запустить задание от имени любого пользователя (просто установите запись crontab для нужного пользователя), но вы правы, что скрипты профиля и входа в систему не будут запускаться, и вы не начнете в своем домашнем каталоге. Поэтому обычно запускать команду с компакт-диска, как показано в комментарии @ luke-franci - person Tom Wilson; 13.01.2017

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

person Tyler Morgan    schedule 11.06.2013

Интересно, что никто не упомянул 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
person Alexander Paramonov    schedule 13.10.2015

Оба будут работать нормально. Я обычно использую скрипт / раннер.

Вот пример:

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. Если вам нужно только вставить несколько записей в базу данных, это будет использовать память, в которой вам действительно не нужно. Если вы напишете свой собственный сценарий, вы можете избежать этого. На самом деле мне это еще не требовалось, но я обдумываю это.

person Luke Francl    schedule 14.11.2008

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

person Thibaut Barrère    schedule 28.12.2008
comment
писать cron-задания так сложно, лучше скачайте гем для этого - person f0ster; 04.02.2013
comment
это несложно, но хранить их в git и всегда в актуальном состоянии при развертывании - это большой плюс, когда человек работает в команде. - person Thibaut Barrère; 17.09.2014

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

http://backgroundrb.rubyforge.org/

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

person salt.racer    schedule 13.11.2008

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

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

person jaysqrd    schedule 24.10.2014
comment
Это правильный ответ. Многие могут забыть о приятных функциях, которые предоставляют sidekiq или resque, например, о веб-интерфейсе для мониторинга того, что происходит: количество запущенных, неудачных или запланированных заданий, их простой перезапуск, блокировка для уникальных рабочих, регулирование и ограничение и т. Д. - person Dmitry Polushkin; 12.03.2015

Вот как я настроил свои задачи cron. У меня есть один, чтобы делать ежедневные резервные копии базы данных SQL (с использованием граблей), а другой - для истечения срока действия кеша один раз в месяц. Любой вывод записывается в файл 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 / 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
person Community    schedule 26.01.2009

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

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

require 'clockwork'

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

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

person Vipul Lawande    schedule 05.11.2015

вы можете использовать resque и resque-schedular gem для создания cron, это очень просто сделать.

https://github.com/resque/resque

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

person Israel Barba    schedule 26.08.2014

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

person Caner Çakmak    schedule 01.04.2014

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

Вы можете посмотреть очень полезное видео на железнодорожных трансляциях

Также взгляните на эти другие ресурсы:

person Adrià Cidre    schedule 14.02.2013
comment
Я безуспешно пытался использовать синтаксис в этом руководстве. Задача не выполнена. - person Tass; 08.07.2013

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

person nnattawat    schedule 03.07.2014

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

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

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

person Stein G. Strindhaug    schedule 13.11.2008

Я использую скрипт для запуска 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. 

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

person Ami    schedule 21.09.2017