Un trabajo cron para rails: ¿mejores prácticas?


¿Cuál es la mejor manera de ejecutar tareas programadas en un entorno Rails? Guión / corredor? ¿Rastrillo?

Author: Philip Morton, 2008-11-13

20 answers

Estoy usando el enfoque de rake (según lo soportado por heroku )

Con un archivo llamado lib/tasks/cron.rastrillo ..

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

Para ejecutar desde la línea de comandos, esto es solo "rastrillo cron". Este comando se puede poner en el sistema operativo cron/programador de tareas como se desee.

Update ¡esta es una vieja pregunta y respuesta! Nueva información:

  • el servicio heroku cron al que me referí ha sido reemplazado por Heroku Planificador
  • para tareas frecuentes (esp. donde desea evitar el costo de inicio del entorno Rails) mi enfoque preferido es usar system cron para llamar a un script que (a) pinchará una API de webhook segura/privada para invocar la tarea requerida en segundo plano o (b) encolará directamente una tarea en su sistema de colas de elección
 108
Author: tardate,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-11 09:40:54

He usado el extremadamente popular Siempre que en proyectos que dependen en gran medida de tareas programadas, y es genial. Le da un buen DSL para definir sus tareas programadas en lugar de tener que lidiar con el formato crontab. Del README:

Whenever es una gema Ruby que proporciona una sintaxis clara para escribir e implementar cron jobs.

Ejemplo del 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
 251
Author: Jim Garvin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-16 20:01:28

Asumiendo que sus tareas no tardan demasiado en completarse, simplemente cree un nuevo controlador con una acción para cada tarea. Implemente la lógica de la tarea como código de controlador, luego configure un cronjob en el nivel del sistema operativo que use wget para invocar la URL de este controlador y la acción en los intervalos de tiempo apropiados. Las ventajas de este método son:

  1. Tenga acceso completo a todos sus objetos Rails como en un controlador normal.
  2. Puede desarrollarse y probarse tal como lo hace normalmente acto.
  3. También puede invocar sus tareas adhoc desde una página web simple.
  4. No consuma más memoria activando procesos ruby/rails adicionales.
 16
Author: Freakent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-30 19:59:35

En nuestro proyecto usamos por primera vez gem, pero nos enfrentamos a algunos problemas.

Luego cambiamos a RUFUS SCHEDULER gem, que resultó ser muy fácil y fiable para programar tareas en Rails.

Lo hemos utilizado para enviar correos semanales y diarios, e incluso para ejecutar algunas tareas periódicas de rake o cualquier método.

El código usado en esto es como:

    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

Para saber más: https://github.com/jmettraux/rufus-scheduler

 15
Author: Pankhuri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-30 07:29:20

El problema con whenever (y cron) es que recarga el entorno rails cada vez que se ejecuta, lo cual es un problema real cuando tus tareas son frecuentes o tienen mucho trabajo de inicialización que hacer. He tenido problemas en la producción debido a esto y debo advertirle.

Rufus scheduler lo hace por mí ( https://github.com/jmettraux/rufus-scheduler )

Cuando tengo trabajos largos que ejecutar, los uso con delayed_job ( https://github.com/collectiveidea/delayed_job )

Espero que esto ayude!

 10
Author: Abdo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-21 22:04:17

Soy un gran fan de resque/resque programador. No solo puede ejecutar tareas repetitivas similares a cron, sino también tareas en momentos específicos. La desventaja es que requiere un servidor Redis.

 10
Author: Tyler Morgan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-11 04:43:25

Las tareas Script/runner y rake están perfectamente bien para ejecutarse como trabajos cron.

Aquí hay una cosa muy importante que debe recordar al ejecutar trabajos cron. Probablemente no se llamarán desde el directorio raíz de tu aplicación. Esto significa que todos los requisitos para los archivos (a diferencia de las bibliotecas) deben hacerse con la ruta explícita: por ejemplo, Archivo.dirname(__FILE__) + "/ other_file". Esto también significa que debe saber cómo llamarlos explícitamente desde otro directorio: -)

Compruebe si su código soporta la ejecución desde otro directorio con

# 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

Además, los trabajos cron probablemente no se ejecuten como tú, así que no dependas de ningún atajo que pongas .bashrc. Pero eso es solo una punta cron estándar; -)

 9
Author: webmat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-13 14:43:53

Ambos funcionarán bien. Normalmente uso script / runner.

Aquí hay un ejemplo:

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

También puede escribir un script pure-Ruby para hacer esto si carga los archivos de configuración correctos para conectarse a su base de datos.

Una cosa a tener en cuenta si la memoria es preciosa es que script/runner (o una tarea de Rake que depende de 'environment') cargará todo el entorno Rails. Si solo necesita insertar algunos registros en la base de datos, esto usará memoria que realmente no tiene a. Si escribes tu propio guión, puedes evitar esto. En realidad no he necesitado hacer esto todavía, pero lo estoy considerando.

 8
Author: Luke Francl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-14 18:19:17

Use Craken (rake centric cron jobs)

 8
Author: Thibaut Barrère,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-28 21:11:22

Eso es interesante nadie mencionó el Sidetiq. Es una buena adición si ya está usando Sidekiq.

Sidetiq proporciona una API simple para definir trabajadores recurrentes para Sidekiq.

Job se verá así:

class MyWorker
  include Sidekiq::Worker
  include Sidetiq::Schedulable

  recurrence { hourly.minute_of_hour(15, 45) }

  def perform
    # do stuff ...
  end
end
 8
Author: AlexParamonov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-14 22:05:57

Uso backgroundrb.

Http://backgroundrb.rubyforge.org /

Lo uso para ejecutar tareas programadas, así como tareas que toman demasiado tiempo para la relación cliente/servidor normal.

 5
Author: salt.racer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-13 00:12:04

Así es como he configurado mis tareas cron. Tengo uno para hacer copias de seguridad diarias de la base de datos SQL (usando rake) y otro para caducar la caché una vez al mes. Cualquier salida se registra en un archivo log/cron_log. Mi crontab se ve así:

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

La primera tarea cron realiza copias de seguridad diarias de la base de datos. El contenido de cron_tasks es el siguiente:

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

La segunda tarea se configuró más tarde y usa script/runner para expirar la caché una vez al mes (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}"

Supongo que podría respaldar base de datos de alguna otra manera, pero hasta ahora funciona para mí:)

Las rutas a rake y ruby pueden variar en diferentes servidores. Puedes ver dónde están usando:

whereis ruby # -> ruby: /usr/local/bin/ruby
whereis rake # -> rake: /usr/local/bin/rake
 3
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-26 15:54:15

Usar algo Sidekiq o Resque es una solución mucho más robusta. Ambos admiten trabajos de reintegro, exclusividad con un bloqueo de REDIS, monitoreo y programación.

Tenga en cuenta que Resque es un proyecto muerto (no mantenido activamente), por lo que Sidekiq es una alternativa mucho mejor. También es más eficiente: Sidekiq ejecuta varios trabajadores en un solo proceso de varios hilos, mientras que Resque ejecuta cada trabajador en un proceso separado.

 3
Author: jaysqrd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-16 18:23:08

Recientemente he creado algunos trabajos cron para los proyectos en los que he estado trabajando.

Encontré que la gema Mecanismo muy útil.

require 'clockwork'

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

Incluso puede programar su trabajo en segundo plano usando esta gema. Para obtener documentación y más ayuda, consulte https://github.com/Rykian/clockwork

 3
Author: Vipul Lawande,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-07 14:42:23

Una vez tuve que tomar la misma decisión y estoy muy contento con esa decisión hoy. Use resque scheduler porque no solo un redis separado eliminará la carga de su base de datos, también tendrá acceso a muchos complementos como resque-web, que proporciona una gran interfaz de usuario. A medida que tu sistema se desarrolle tendrás más y más tareas que programar por lo que podrás controlarlas desde un solo lugar.

 2
Author: Caner Çakmak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-01 20:07:14

Puede usar resque y resque-shheduler gem para crear crons, esto es muy fácil de hacer.

Https://github.com/resque/resque

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

 2
Author: Israel Barba,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-26 18:10:29

Probablemente la mejor manera de hacerlo es usar rake para escribir las tareas que necesita y simplemente ejecutarlo a través de la línea de comandos.

Puedes ver un video muy útil en railscasts

También eche un vistazo a estos otros recursos:

 1
Author: Adrià Cidre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-14 20:17:35

Usé clockwork gem y funciona bastante bien para mí. También hay una gema clockworkd que permite que un script se ejecute como un demonio.

 1
Author: nnattawat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-03 02:33:28

No estoy muy seguro, supongo que depende de la tarea: la frecuencia de ejecución, la complejidad y la comunicación directa con el proyecto rails, etc. Supongo que si solo hubiera "Una Mejor Manera" de hacer algo, no habría tantas maneras diferentes de hacerlo.

En mi último trabajo en un proyecto Rails, necesitábamos hacer un correo de invitación por lotes (invitaciones a encuestas, no spamming) que debería enviar los correos planificados cada vez que el servidor tuviera tiempo. Creo que estábamos voy a usar daemon tools para ejecutar las tareas de rake que había creado.

Desafortunadamente, nuestra compañía tuvo algunos problemas de dinero y fue "comprada" por el principal rival, por lo que el proyecto nunca se completó, por lo que no se qué habríamos usado eventualmente.

 0
Author: Stein G. Strindhaug,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-22 14:52:12

Utilizo script para ejecutar cron, esa es la mejor manera de ejecutar un cron. Aquí hay un ejemplo para cron,

Abrir CronTab - > sudo crontab-e

Y Pegue Las líneas De Abajo:

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

Aquí hay algunos cron formato, le ayudará

::CRON FORMAT::

tabla de formato 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. 

Espero que esto te ayude:)

 0
Author: Ami,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-21 10:27:45