Часто возникает необходимость в приложениях на рельсах запускать какие-то скрипты cron’ом. Однако, желательно не просто запустить скрипт, для этого особого ума не надо, а написать скрипт и запустить его так чтобы он использовал интерфейсы Rails т.е. ROR-методы работы с БД, короче говоря Active Records.
Способами как сделать cron-скрипт для Rails 2.x исписан весь интернет. Собственно в Rails 3.x все практически также.
Открываем какую-нибудь модель или создаем новую, пусть это будет rails_app/app/models/product.rb
:
1 2 3 | class Product < ActiveRecord::Base #возможно здесь что-то есть end |
И дописываем в класс метод собственно с самим нашим заданием, например:
1 2 3 4 5 6 7 | class Product < ActiveRecord::Base def crontask fl=File.new('crontask_result','w') fl.puts Time.now fl.close end end |
А теперь чтобы запустить написанный метод пишем в консоли или cron’е так:
1 2 | $ RAILS_ENV=production ruby rails_app/script/rails runner Product.crontask |
В результате чего в корне rails_app
будет создан файл crontask_result
со временем запуска скрипта.
Это все понятно и легко, но порой при запуске методов, написанных под крон вылетает ошибка а-ля:
1 2 3 | /usr/local/lib/ruby/gems/1.9.1/gems/railties-3.0.3/lib/rails /commands/runner.rb:50:in `eval': "\x8B" from ASCII-8BIT to UTF-8 (Encoding::UndefinedConversionError) |
Почитав переписку самого Юкихиро Мацумото со многими, я так понил, что этот баг не исправлен. Поэтому решаем эту проблему тупо в лоб, разбиваем метод, на части:
- где содержатся или обрабатываются не ASCII символы переносим в отдельные скрипты, не связанные с Rails
- где все ASCII пишем в метод и через
system()
вызываем первую категорию скриптов, а также здесь осуществляем необходимую связь первых скриптов с Rails Active Records
Как будут передаватся данные из первых скриптов вторым абсолютно все равно, через временные файлы, сокеты, кодом завершения итд.
У кого есть варианты получше пишите в комментариях.
А можно и вообще крон не использовать:
https://github.com/javan/whenever
посмотрел, прикольная штука.
Единственное, я думаю что жрет процессора она больше чем крон т.к. Руби не Си
чтобы не забыть.
Лучше запускать кроновый методы не так как я писал выше (в том случае Active Records может не работать), а так:
rails runner -e production 'Product.crontask'
ruby rails_app/script/rails runner -e production 'Product.crontask'
В Rails общепринятый метод писать скрипты, запускаемые с командной строки – Rake. Вот, например, нисколько не устаревший рельскаст на эту тему: http://railscasts.com/episodes/66-custom-rake-tasks
Преимущества Rake-тасок перед тем, что вы делаете – в первую очередь, то, что они наглядны.
Кстати, whenever – это удобный способ наполнять crontab из руби, не более того (и очень полезный). Это не самостоятельный планировщик, не знаю где вы это вычитали, и ресурсов он не ест в принципе.
[...] rake. Об этом способе я узнал из комментария к статье задания cron в ROR 3, который написал Леонид Шевцов, приведя ссылку на [...]