Un travail cron pour rails: les meilleures pratiques?

Quelle est la meilleure façon d'exécuter des tâches planifiées dans un environnement Rails? Script / coureur? Râteau?

287
demandé sur Philip Morton 2008-11-13 01:59:50

20 réponses

J'utilise l'approche rake (comme supporté par heroku )

Avec un fichier appelé lib/tasks/cron.râteau ..

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

Pour exécuter à partir de la ligne de commande, c'est juste "râteau " cron". Cette commande peut ensuite être placée sur le système d'exploitation cron/planificateur de tâches comme vous le souhaitez.

Update c'est une question et une réponse assez anciennes! Quelques nouvelles infos:

  • le service Heroku cron que j'ai référencé a depuis été remplacé par Heroku Planificateur
  • pour les tâches fréquentes (esp. où vous voulez éviter le coût de démarrage de L'environnement Rails) mon approche préférée est d'utiliser system cron pour appeler un script qui (a) lancera une API webhook sécurisée/privée pour appeler la tâche requise en arrière-plan ou (b) mettra directement en file d'attente une tâche sur votre système de file d'attente de choix
108
répondu tardate 2015-02-11 09:40:54

J'ai utilisé le très populaire chaque fois que sur des projets qui reposent fortement sur des tâches planifiées, et c'est génial. Il vous donne un bon DSL pour définir vos tâches planifiées au lieu d'avoir à traiter avec le format crontab. Du README:

Whenever est une gemme de rubis qui fournit un syntaxe claire pour l'écriture et le déploiement cron.

Exemple du fichier 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
répondu Jim Garvin 2011-06-16 20:01:28

En supposant que vos tâches ne prennent pas trop de temps à terminer, créez simplement un nouveau contrôleur avec une action pour chaque tâche. Implémentez la logique de la tâche en tant que code de contrôleur, puis configurez un cronjob au niveau du système D'exploitation qui utilise wget pour appeler L'URL de ce contrôleur et l'action aux intervalles de temps appropriés. Les avantages de cette méthode sont vous:

  1. avoir un accès complet à tous vos objets Rails comme dans un contrôleur normal.
  2. peut développer et tester comme vous le faites normalement action.
  3. peut également appeler vos tâches adhoc à partir d'une simple page web.
  4. Ne consommez plus de mémoire en déclenchant des processus ruby/rails supplémentaires.
16
répondu Freakent 2012-05-30 19:59:35

Dans notre projet, nous avons d'abord utilisé chaque fois que gem, mais confronté à certains problèmes.

Nous sommes ensuite passés à planificateur RUFUS gem, qui s'est avéré très facile et fiable pour la planification des tâches dans Rails.

Nous l'avons utilisé pour envoyer des mails hebdomadaires et quotidiens, et même pour exécuter des tâches de râteau périodiques ou n'importe quelle méthode.

Le code utilisé dans ceci est comme:

    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

Pour en savoir plus: https://github.com/jmettraux/rufus-scheduler

15
répondu Pankhuri 2013-08-30 07:29:20

Le problème avec whenever (et cron) est qu'il recharge l'environnement rails chaque fois qu'il est exécuté, ce qui est un vrai problème lorsque vos tâches sont fréquentes ou ont beaucoup de travail d'initialisation à faire. J'ai eu des problèmes en production à cause de cela et je dois vous avertir.

Rufus planificateur de ne pour moi ( https://github.com/jmettraux/rufus-scheduler )

Quand j'ai de longs travaux à exécuter, Je l'utilise avec delayed_job ( https://github.com/collectiveidea/delayed_job )

J'espère que cela aide!

10
répondu Abdo 2013-02-21 22:04:17

Je suis un grand fan de resque/resque planificateur de. Vous pouvez non seulement exécuter des tâches répétitives de type cron, mais aussi des tâches à des moments spécifiques. L'inconvénient est, il nécessite un serveur Redis.

10
répondu Tyler Morgan 2013-06-11 04:43:25

Les tâches Script/runner et rake sont parfaitement bien à exécuter en tant que tâches cron.

Voici une chose très importante dont vous devez vous souvenir lors de l'exécution des travaux cron. Ils ne seront probablement pas appelés à partir du répertoire racine de votre application. Cela signifie que tous vos besoins pour les fichiers (par opposition aux bibliothèques)doivent être faits avec le chemin explicite: par exemple File.dirname (__FILE__) + "/other_file". Cela signifie également que vous devez savoir comment appeler explicitement à partir d'un autre répertoire :-)

Vérifiez si votre code prend en charge l'exécution à partir d'un autre répertoire avec

# 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

En outre, les travaux cron ne fonctionnent probablement pas comme vous, donc ne dépendent d'aucun raccourci que vous mettez .bashrc. Mais c'est juste une pointe de cron standard ; -)

9
répondu webmat 2008-11-13 14:43:53

Les deux fonctionneront bien. J'utilise habituellement script / runner.

Voici un exemple:

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

Vous pouvez également écrire un script pur-Ruby pour le faire si vous chargez les bons fichiers de configuration pour vous connecter à votre base de données.

Une chose à garder à l'esprit si la mémoire est précieuse est que script/runner (ou une tâche Rake qui dépend de 'environment') chargera l'environnement Rails entier. Si vous avez seulement besoin d'insérer des enregistrements dans la base de données, cela utilisera la mémoire que vous n'avez pas vraiment de. Si vous écrivez votre propre script, vous pouvez éviter cela. Je n'ai pas réellement besoin de faire cela, mais j'envisage de me il.

8
répondu Luke Francl 2008-11-14 18:19:17

Utiliser Craken (tâches cron centrées sur le râteau)

8
répondu Thibaut Barrère 2008-12-28 21:11:22

C'est intéressant personne n'a mentionné le Sidetiq . C'est une belle addition si vous utilisez déjà Sidekiq.

Sidetiq fournit une API simple pour définir des travailleurs récurrents pour Sidekiq.

Travail ressemblera à ceci:

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

  recurrence { hourly.minute_of_hour(15, 45) }

  def perform
    # do stuff ...
  end
end
8
répondu AlexParamonov 2015-10-14 22:05:57

J'utilise backgroundrb.

Http://backgroundrb.rubyforge.org/

Je l'utilise pour exécuter des tâches planifiées ainsi que des tâches qui prennent trop de temps pour la relation client/serveur normale.

5
répondu salt.racer 2008-11-13 00:12:04

Voici comment j'ai configuré mes tâches cron. J'en ai un pour faire des sauvegardes quotidiennes de la base de données SQL (en utilisant rake) et un autre pour expirer le cache une fois par mois. Toute sortie est enregistrée dans un fichier log / cron_log. Mon crontab ressemble à ceci:

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 première tâche cron effectue des sauvegardes db quotidiennes. Le contenu de cron_tasks est le suivant:

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

La deuxième tâche a été configurée plus tard et utilise script / runner pour expirer le cache une fois par mois (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}"

Je suppose que je pourrais sauvegarder base de données d'une autre manière mais jusqu'à présent cela fonctionne pour moi:)

Les chemins vers rake et ruby peuvent varier sur différents serveurs. Vous pouvez voir où ils sont en utilisant:

whereis ruby # -> ruby: /usr/local/bin/ruby
whereis rake # -> rake: /usr/local/bin/rake
3
répondu 2009-01-26 15:54:15

Utiliser quelque chose Sidekiq ou Resque est une solution beaucoup plus robuste. Ils prennent tous deux en charge les travaux de réessaiement, l'exclusivité avec un verrou REDIS, la surveillance et la planification.

Gardez à l'esprit que Resque est un projet mort (pas activement maintenu), donc Sidekiq est une meilleure alternative. Il est également plus performant: Sidekiq exécute plusieurs travailleurs sur un seul processus multithread tandis que Resque exécute chaque travailleur dans un processus séparé.

3
répondu jaysqrd 2015-09-16 18:23:08

J'ai récemment créé des emplois cron pour les projets sur lesquels je travaille.

J'ai trouvé que la gemme Clockwork très utile.

require 'clockwork'

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

Vous pouvez même planifier votre travail d'arrière-plan en utilisant cette gemme. Pour la documentation et l'aide supplémentaire, reportez-vous à https://github.com/Rykian/clockwork

3
répondu Vipul Lawande 2017-12-07 14:42:23

Une fois, j'ai dû prendre la même décision et je suis vraiment heureux de cette décision aujourd'hui. Utilisez resque scheduler parce que non seulement un Redis séparé prendra la charge de votre base de données, vous aurez également accès à de nombreux plugins comme resque-web qui fournit une excellente interface utilisateur. Au fur et à mesure que votre système se développe, vous aurez de plus en plus de tâches à planifier afin que vous puissiez les contrôler à partir d'un seul endroit.

2
répondu Caner Çakmak 2014-04-01 20:07:14

Vous pouvez utiliser resque et resque - shheduler gem pour créer des crons, c'est très facile à faire.

Https://github.com/resque/resque

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

2
répondu Israel Barba 2014-08-26 18:10:29

Probablement la meilleure façon de le faire est d'utiliser rake pour écrire les tâches dont vous avez besoin et de l'exécuter simplement via la ligne de commande.

Vous pouvez voir une vidéo très utile sur railscasts

Jetez également un oeil à ces autres ressources:

1
répondu Adrià Cidre 2013-02-14 20:17:35

J'ai utiliséclockwork gem et cela fonctionne plutôt bien pour moi. Il y a aussi clockworkd gem qui permet à un script de s'exécuter en tant que démon.

1
répondu nnattawat 2014-07-03 02:33:28

Je ne suis pas vraiment sûr, je suppose que cela dépend de la tâche: combien de fois courir, combien compliqué et combien de communication directe avec le projet rails est nécessaire, etc. Je suppose que s'il y avait juste "Une Meilleure Façon" de faire quelque chose, il n'y aurait pas beaucoup de façons différentes de le faire.

Lors de mon dernier travail dans un projet Rails, nous devions créer un mailer d'invitation par lots (invitations d'enquête, pas de spamming) qui devrait envoyer les mails planifiés chaque fois que le serveur avait le temps. Je pense que nous avons été allez utiliser daemon tools pour exécuter les tâches rake que j'avais créé.

Malheureusement, notre entreprise a eu des problèmes d'argent et a été "achetée" par le principal rival, donc le projet n'a jamais été achevé, donc je ne sais pas ce que nous aurions finalement utilisé.

0
répondu Stein G. Strindhaug 2015-09-22 14:52:12

J'utilise un script pour exécuter cron, c'est la meilleure façon d'exécuter un cron. Voici un exemple pour cron,

Ouvrir CronTab- > sudo crontab-e

Et coller ci-dessous lignes:

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

Voici un format cron, vous aidera

::CRON FORMAT::

table de 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. 

J'espère que cela vous aidera:)

0
répondu Ami 2017-09-21 10:27:45