Quelle est la meilleure façon d'exécuter des tâches planifiées dans un environnement Rails? Script / coureur? Râteau? Je voudrais exécuter la tâche toutes les quelques minutes.
Quelle est la meilleure façon d'exécuter des tâches planifiées dans un environnement Rails? Script / coureur? Râteau? Je voudrais exécuter la tâche toutes les quelques minutes.
Réponses:
J'utilise l'approche de râteau (telle que prise en charge par Heroku )
Avec un fichier appelé lib / tasks / cron.rake ..
task :cron => :environment do
puts "Pulling new requests..."
EdiListener.process_new_messages
puts "done."
end
Pour exécuter à partir de la ligne de commande, il s'agit simplement de "rake cron". Cette commande peut ensuite être placée sur le planificateur cron / tâche du système d'exploitation comme vous le souhaitez.
Mettre à jour c'est une question et une réponse assez anciennes! Quelques nouvelles infos:
load "#{Rails.root}/lib/tasks/cron.rake"
et rake cron
, mais j'ai obtenu NameError: variable locale non définie ou méthode `cron 'pour main: Object
:environment
dépendance. Nous avons une application Rails très lourde qui prend du temps à démarrer, notre Rake est appelé toutes les minutes et consomme plus de ressources au démarrage de l' environnement Rails qui exécute la tâche . J'aimerais avoir un environnement Rails déjà démarré pour être appelé via le cron, être quelque chose entre l' approche du contrôleur et celle de l' environnement rake .
J'ai utilisé le très populaire Whenever sur des projets qui reposent fortement sur des tâches planifiées, et c'est génial. Il vous donne une belle DSL pour définir vos tâches planifiées au lieu d'avoir à gérer le format crontab. Du README:
Chaque fois qu'il s'agit d'un joyau Ruby qui fournit une syntaxe claire pour l'écriture et le déploiement de tâches cron.
Exemple du 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
Dans notre projet, nous avons d'abord utilisé chaque fois que gem, mais nous avons rencontré des problèmes.
Nous sommes ensuite passés à RUFUS SCHEDULER 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 courriers hebdomadaires et quotidiens, et même pour exécuter des tâches de râteau périodiques ou toute autre méthode.
Le code utilisé ici 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
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 agir aux intervalles de temps appropriés. Les avantages de cette méthode sont les suivants:
les tâches script / runner et rake sont parfaitement adaptées à l'exécution en tant que tâches cron.
Voici une chose très importante à retenir lors de l'exécution de tâches cron. Ils ne seront probablement pas appelés depuis le répertoire racine de votre application. Cela signifie que tout ce dont vous avez besoin pour les fichiers (par opposition aux bibliothèques) doit être fait avec le chemin explicite: par exemple File.dirname (__ FILE__) + "/ other_file". Cela signifie également que vous devez savoir comment les 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
De plus, les tâches cron ne s'exécutent probablement pas comme vous, donc ne dépendez pas des raccourcis que vous mettez dans .bashrc. Mais ce n'est qu'une astuce cron standard ;-)
Le problème à chaque fois (et cron) est qu'il recharge l'environnement des rails à chaque exécution, 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 de production à cause de cela et je dois vous avertir.
L'ordonnanceur Rufus le fait pour moi ( https://github.com/jmettraux/rufus-scheduler )
Lorsque j'ai de longs travaux à exécuter, je l'utilise avec delay_job ( https://github.com/collectiveidea/delayed_job )
J'espère que ça aide!
Je suis un grand fan de resque / resque scheduler . Vous pouvez non seulement exécuter des tâches répétitives de type cron, mais également des tâches à des moments spécifiques. L'inconvénient est qu'il nécessite un serveur Redis.
C'est intéressant, personne n'a mentionné le Sidetiq . C'est un ajout intéressant si vous utilisez déjà Sidekiq.
Sidetiq fournit une API simple pour définir des travailleurs récurrents pour Sidekiq.
Le travail ressemblera à ceci:
class MyWorker
include Sidekiq::Worker
include Sidetiq::Schedulable
recurrence { hourly.minute_of_hour(15, 45) }
def perform
# do stuff ...
end
end
Les deux fonctionneront bien. J'utilise généralement un 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 Ruby pur pour ce 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 le script / runner (ou une tâche Rake qui dépend de «l'environnement») chargera tout l'environnement Rails. Si vous avez seulement besoin d'insérer des enregistrements dans la base de données, cela utilisera de la mémoire dont vous n'avez pas vraiment besoin. Si vous écrivez votre propre script, vous pouvez éviter cela. Je n'ai pas encore eu besoin de le faire, mais j'y réfléchis.
Utiliser Craken (travaux cron centrés sur le râteau)
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.
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 le râteau) et un autre pour expirer le cache une fois par mois. Toute sortie est enregistrée dans un fichier journal / 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 quotidiennes de la base de données. 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 un script / runner pour expirer le cache une fois par mois (lib / mensuel_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 la base de données d'une autre manière, mais jusqu'à présent, cela fonctionne pour moi :)
Les chemins d' accès au râteau et au rubis peuvent varier sur différents serveurs. Vous pouvez voir où ils se trouvent en utilisant:
whereis ruby # -> ruby: /usr/local/bin/ruby
whereis rake # -> rake: /usr/local/bin/rake
Utiliser quelque chose de Sidekiq ou Resque est une solution beaucoup plus robuste. Ils prennent tous deux en charge les nouvelles tentatives, l'exclusivité avec un verrou REDIS, la surveillance et la planification.
Gardez à l'esprit que Resque est un projet mort (non activement maintenu), Sidekiq est donc une bien 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 distinct.
J'ai récemment créé des emplois cron pour les projets sur lesquels je travaille.
J'ai trouvé que le joyau Clockwork était 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 ce joyau. Pour la documentation et l'aide supplémentaire, consultez https://github.com/Rykian/clockwork
vous pouvez utiliser resque
et resque-schedular
gem pour créer cron, c'est très facile à faire.
Une fois, j'ai dû prendre la même décision et je suis vraiment content de cette décision aujourd'hui. Utilisez l' ordonnanceur resque car non seulement un redis séparé supprimera 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.
La meilleure façon de le faire est probablement d'utiliser rake pour écrire les tâches dont vous avez besoin et de simplement l'exécuter via la ligne de commande.
Vous pouvez voir un très utile vidéo sur railscasts
Jetez également un œil à ces autres ressources:
J'ai utilisé un bijou d' horlogerie et cela fonctionne assez bien pour moi. Il existe également une clockworkd
gemme qui permet à un script de s'exécuter en tant que démon.
Je ne suis pas vraiment sûr, je suppose que cela dépend de la tâche: à quelle fréquence exécuter, combien compliqué et combien de communication directe avec le projet de rails est nécessaire, etc. Je suppose que s'il y avait juste "One Best Way" pour faire quelque chose , il n'y aurait pas tant de façons différentes de le faire.
Lors de mon dernier emploi dans un projet Rails, nous devions créer un mailing d'invitation par lots (invitations à des sondages, pas de spam) qui devrait envoyer les mails planifiés chaque fois que le serveur en avait le temps. Je pense que nous allions utiliser des outils démon pour exécuter les tâches de râteau que j'avais créées.
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é.
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 collez les lignes ci-dessous:
00 00 * * * wget https: // your_host / some_API_end_point
Voici un certain format cron, vous aidera
::CRON FORMAT::
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 ceci vous aidera :)