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

300

Какой лучший способ запускать запланированные задачи в среде Rails? Script/бегун? Рейк?

  • 0
    как часто будет выполняться задание?
  • 0
    часто! каждые несколько минут
Показать ещё 6 комментариев
Теги:
cron
rake
daemon

20 ответов

113
Лучший ответ

Я использую подход рейка (поддерживаемый 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) непосредственно поставить в очередь задачу в выбранной вашей системе ожидания
  • 0
    Какой должна быть запись cron для этого случая, чтобы ОС знала правильный путь к задаче rake?
  • 13
    NB: в эти дни я использую всякий раз (см. Ответ Джима Гарвина), но необработанная запись cron для запуска задачи rake будет выглядеть примерно так: 30 4 * * * / bin / bash -l -c 'cd / opt / railsapp && RAILS_ENV = производственные грабли cron --silent '
Показать ещё 7 комментариев
262

Я использовал чрезвычайно популярный 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
  • 21
    Если он запускается каждую минуту, среда будет перезапускаться каждый раз, что может быть дорогостоящим. Похоже, что github.com/ssoroka/scheduler_daemon избегает этого.
  • 3
    +1 за сохранение конфигурации cron в вашей системе контроля версий
Показать ещё 4 комментария
15

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

Затем мы переключились на 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

  • 1
    На rufus, так как я использовал его как для простых проектов ruby, так и для полнофункциональных приложений.
  • 6
    Не могли бы вы рассказать о проблемах, с которыми вы столкнулись?
15

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

  • Полный доступ ко всем объектам Rails, как и к обычным контроллерам.
  • Может развиваться и тестироваться так же, как вы делаете обычные действия.
  • Можно также вызвать ваши задачи adhoc с простой веб-страницы.
  • Не потребляйте больше памяти, запуская дополнительные процессы ruby ​​/rails.
  • 12
    Как запретить другим доступ к этой задаче? Если задача, принимающая процессор и вызывающая ее часто, вызовет проблемы.
  • 0
    Так же, как и для любого другого контроллера. Убедитесь, что вы реализуете какую-то защиту - AuthLogic или restful_authentication, затем добавьте управление ролями поверх этого с помощью acl9 или чего-то еще. Затем вы можете использовать свое приложение rails для обслуживания всех задач через спокойный интерфейс с безопасностью и прочим, как и любой другой веб-сервис. Это дает такие вещи, как: вы можете использовать свой Домен для аутентификации и позволить «серверному» пользователю запускать задачи, запланированные в cron или Scheduled Tasks, если вы используете windows. Также это позволяет вам получить доступ к тем же вещам через скрипт / бегуна, если вам нужно. Продолжение в следующем комментарии.
Показать ещё 11 комментариев
10

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

10

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

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

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

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

9

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

  • 0
    Вы можете запускать задание от имени любого пользователя (просто установите запись в crontab для нужного вам пользователя), но вы правы в том, что профили и сценарии входа в систему не будут запускаться и вы не запустите в своем домашнем каталоге. Поэтому обычно команду запускают с "cd", как показано в комментарии @ luke-franci
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
8

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

  • 0
    Это классный инструмент, спасибо.
  • 0
    Рад, что это помогло!
Показать ещё 2 комментария
8

Оба будут работать нормально. Обычно я использую 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, вы можете избежать этого. Мне на самом деле не нужно было этого делать, но я рассматриваю это.

5

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

http://backgroundrb.rubyforge.org/

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

3

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

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

require 'clockwork'

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

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

3

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

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

  • 0
    Это правильный ответ. Многие могут забыть о приятных функциях, которые предоставляет sidekiq или resque, таких как веб-интерфейс для мониторинга происходящего: количество запущенных, сбойных или запланированных заданий, их легкий перезапуск, блокировка для уникальных работников, регулирование и ограничение и т. Д.
3

Вот как я установил свои задачи 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
2

вы можете использовать драгоценный камень resque и resque-shheduler для создания кронов, это очень легко сделать.

https://github.com/resque/resque

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

2

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

1

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

1

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

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

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

  • 0
    Я безуспешно пытался использовать синтаксис в этом уроке. Задача не была выполнена.
0

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

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

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

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

Вот некоторый формат cron, поможет вам

::CRON FORMAT::

Изображение 4159

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. 

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

0

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

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню