Was ist der beste Weg, um geplante Aufgaben in einer Rails-Umgebung auszuführen? Skript / Läufer? Rechen? Ich möchte die Aufgabe alle paar Minuten ausführen.
Was ist der beste Weg, um geplante Aufgaben in einer Rails-Umgebung auszuführen? Skript / Läufer? Rechen? Ich möchte die Aufgabe alle paar Minuten ausführen.
Antworten:
Ich verwende den Rake-Ansatz (wie von Heroku unterstützt )
Mit einer Datei namens lib / task / cron.rake ..
task :cron => :environment do
puts "Pulling new requests..."
EdiListener.process_new_messages
puts "done."
end
Für die Ausführung über die Befehlszeile ist dies nur "Rake Cron". Dieser Befehl kann dann wie gewünscht auf dem Cron / Task-Scheduler des Betriebssystems abgelegt werden.
Update das ist eine ziemlich alte Frage und Antwort! Einige neue Infos:
load "#{Rails.root}/lib/tasks/cron.rake"
und rake cron
, aber NameError: undefinierte lokale Variable oder Methode `cron 'für main: Object
:environment
Abhängigkeit. Wir haben eine sehr schwere Rails-Anwendung, deren Start lange dauert. Unser Rake wird jede Minute aufgerufen und verbraucht mehr Ressourcen, um die Rails-Umgebung zu starten, in der die Aufgabe ausgeführt wird . Ich würde gerne eine bereits gestartete Rails-Umgebung haben, die über den Cron aufgerufen werden kann. Sie muss etwas zwischen dem Controller- Ansatz und der Rake-Umgebung sein .
Ich habe das äußerst beliebte Wann immer für Projekte verwendet, die stark von geplanten Aufgaben abhängen, und es ist großartig. Es gibt Ihnen ein nettes DSL, um Ihre geplanten Aufgaben zu definieren, anstatt sich mit dem Crontab-Format befassen zu müssen. Aus der README:
Wann immer es sich um ein Ruby-Juwel handelt, das eine klare Syntax zum Schreiben und Bereitstellen von Cron-Jobs bietet.
Beispiel aus der 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
In unserem Projekt haben wir zuerst immer Edelsteine verwendet, waren aber mit einigen Problemen konfrontiert.
Wir haben dann zu RUFUS SCHEDULER gem gewechselt , was sich als sehr einfach und zuverlässig für die Planung von Aufgaben in Rails herausstellte.
Wir haben es zum Versenden von wöchentlichen und täglichen E-Mails und sogar zum Ausführen einiger periodischer Rechenaufgaben oder einer anderen Methode verwendet.
Der hier verwendete Code lautet wie folgt:
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
Weitere Informationen : https://github.com/jmettraux/rufus-scheduler
Angenommen, die Ausführung Ihrer Aufgaben dauert nicht zu lange. Erstellen Sie einfach einen neuen Controller mit einer Aktion für jede Aufgabe. Implementieren Sie die Logik der Aufgabe als Controller-Code. Richten Sie dann einen Cronjob auf Betriebssystemebene ein, der mit wget die URL dieses Controllers und die Aktion in den entsprechenden Zeitintervallen aufruft. Die Vorteile dieser Methode sind Sie:
Skript- / Runner- und Rake-Aufgaben können problemlos als Cron-Jobs ausgeführt werden.
Hier ist eine sehr wichtige Sache, an die Sie denken müssen, wenn Sie Cron-Jobs ausführen. Sie werden wahrscheinlich nicht aus dem Stammverzeichnis Ihrer App aufgerufen. Dies bedeutet, dass alle Ihre Anforderungen an Dateien (im Gegensatz zu Bibliotheken) mit dem expliziten Pfad ausgeführt werden sollten: z. B. File.dirname (__ FILE__) + "/ other_file". Dies bedeutet auch, dass Sie wissen müssen, wie Sie sie explizit aus einem anderen Verzeichnis aufrufen können :-)
Überprüfen Sie, ob Ihr Code die Ausführung aus einem anderen Verzeichnis mit unterstützt
# 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
Außerdem werden Cron-Jobs wahrscheinlich nicht so ausgeführt wie Sie. Sie hängen also nicht von einer Verknüpfung ab, die Sie in .bashrc eingegeben haben. Aber das ist nur eine Standard-Cron-Spitze ;-)
Das Problem bei jedem (und jedem) Cron ist, dass die Rails-Umgebung bei jeder Ausführung neu geladen wird. Dies ist ein echtes Problem, wenn Ihre Aufgaben häufig sind oder viel Initialisierungsarbeit zu erledigen ist. Ich hatte deswegen Probleme in der Produktion und muss Sie warnen.
Rufus Scheduler erledigt das für mich ( https://github.com/jmettraux/rufus-scheduler )
Wenn ich lange Jobs ausführen muss, verwende ich sie mit verzögertem Job ( https://github.com/collectiveidea/delayed_job ).
Ich hoffe das hilft!
Ich bin ein großer Fan von Resque / Resque Scheduler . Sie können nicht nur sich wiederholende Cron-ähnliche Aufgaben ausführen, sondern auch Aufgaben zu bestimmten Zeiten. Der Nachteil ist, dass ein Redis-Server erforderlich ist.
Das ist interessant, niemand hat den Sidetiq erwähnt . Es ist eine schöne Ergänzung, wenn Sie bereits Sidekiq verwenden.
Sidetiq bietet eine einfache API zum Definieren wiederkehrender Worker für Sidekiq.
Job wird so aussehen:
class MyWorker
include Sidekiq::Worker
include Sidetiq::Schedulable
recurrence { hourly.minute_of_hour(15, 45) }
def perform
# do stuff ...
end
end
Beides wird gut funktionieren. Normalerweise benutze ich Script / Runner.
Hier ist ein Beispiel:
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
Sie können dazu auch ein reines Ruby-Skript schreiben, wenn Sie die richtigen Konfigurationsdateien laden, um eine Verbindung zu Ihrer Datenbank herzustellen.
Eine Sache, die Sie beachten sollten, wenn Speicher wertvoll ist, ist, dass Skript / Runner (oder eine Rake-Aufgabe, die von der Umgebung abhängt) die gesamte Rails-Umgebung lädt. Wenn Sie nur einige Datensätze in die Datenbank einfügen müssen, wird Speicher benötigt, den Sie nicht wirklich benötigen. Wenn Sie Ihr eigenes Skript schreiben, können Sie dies vermeiden. Ich musste das noch nicht tun, aber ich denke darüber nach.
Verwenden Sie Craken (Rake-zentrierte Cron-Jobs)
Ich benutze backgroundrb.
http://backgroundrb.rubyforge.org/
Ich verwende es, um geplante Aufgaben sowie Aufgaben auszuführen, die für die normale Client / Server-Beziehung zu lange dauern.
So habe ich meine Cron-Aufgaben eingerichtet. Ich habe eine, um tägliche Backups der SQL-Datenbank (mit Rake) zu erstellen, und eine andere, um den Cache einmal im Monat abzulaufen. Jede Ausgabe wird in einer Datei log / cron_log protokolliert. Mein Crontab sieht so aus:
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
Die erste Cron-Aufgabe erstellt tägliche DB-Backups. Der Inhalt von cron_tasks lautet wie folgt:
/usr/local/bin/rake db:backup RAILS_ENV=production; date; echo "END OF OUTPUT ----";
Die zweite Aufgabe wurde später eingerichtet und verwendet Script / Runner, um den Cache einmal im Monat abzulaufen (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}"
Ich denke, ich könnte die Datenbank auf andere Weise sichern, aber bisher funktioniert es für mich :)
Die Pfade zu Rake und Ruby können auf verschiedenen Servern variieren. Sie können sehen, wo sie sind, indem Sie:
whereis ruby # -> ruby: /usr/local/bin/ruby
whereis rake # -> rake: /usr/local/bin/rake
Die Verwendung von Sidekiq oder Resque ist eine weitaus robustere Lösung. Beide unterstützen das Wiederholen von Jobs, die Exklusivität mit einer REDIS-Sperre, die Überwachung und die Planung.
Denken Sie daran, dass Resque ein totes Projekt ist (nicht aktiv gewartet), daher ist Sidekiq eine viel bessere Alternative. Es ist auch leistungsfähiger: Sidekiq führt mehrere Worker in einem einzigen Multithread-Prozess aus, während Resque jeden Worker in einem separaten Prozess ausführt.
Ich habe kürzlich einige Cron-Jobs für die Projekte geschaffen, an denen ich gearbeitet habe.
Ich fand das Juwel Clockwork sehr nützlich.
require 'clockwork'
module Clockwork
every(10.seconds, 'frequent.job')
end
Mit diesem Juwel können Sie sogar Ihren Hintergrundjob planen. Dokumentation und weitere Hilfe finden Sie unter https://github.com/Rykian/clockwork
Sie können resque
und resque-schedular
Edelstein für die Erstellung von Cron verwenden, dies ist sehr einfach zu tun.
Einmal musste ich die gleiche Entscheidung treffen und bin heute sehr zufrieden mit dieser Entscheidung. Verwenden Sie den Resque-Scheduler, da nicht nur ein separater Redis die Last von Ihrer Datenbank entlastet, sondern Sie auch Zugriff auf viele Plugins wie resque-web haben, die eine großartige Benutzeroberfläche bieten. Während sich Ihr System entwickelt, müssen Sie immer mehr Aufgaben planen, damit Sie sie von einem einzigen Ort aus steuern können.
Der wahrscheinlich beste Weg, dies zu tun, ist die Verwendung von Rake, um die benötigten Aufgaben zu schreiben und sie einfach über die Befehlszeile auszuführen.
Sie können ein sehr hilfreiches Video bei Railscasts sehen
Schauen Sie sich auch diese anderen Ressourcen an:
Ich bin mir nicht sicher, ich denke, es hängt von der Aufgabe ab: wie oft ausgeführt werden soll, wie kompliziert und wie viel direkte Kommunikation mit dem Rails-Projekt erforderlich ist usw. Ich denke, wenn es nur "One Best Way" gab. , um etwas zu tun Es würde nicht so viele verschiedene Möglichkeiten geben, dies zu tun.
Bei meinem letzten Job in einem Rails-Projekt mussten wir einen Batch-Einladungs-Mailer (Umfrageeinladungen, kein Spam) erstellen, der die geplanten E-Mails senden sollte, wann immer der Server Zeit hatte. Ich denke, wir wollten Daemon-Tools verwenden , um die von mir erstellten Rake-Aufgaben auszuführen.
Leider hatte unser Unternehmen einige Geldprobleme und wurde vom Hauptkonkurrenten "gekauft", so dass das Projekt nie abgeschlossen wurde, sodass ich nicht weiß, was wir letztendlich verwendet hätten.
Ich benutze Skript, um Cron auszuführen, das ist der beste Weg, um Cron auszuführen. Hier ist ein Beispiel für cron,
Öffnen Sie CronTab -> sudo crontab -e
Und fügen Sie die folgenden Zeilen ein:
00 00 * * * wget https: // your_host / some_API_end_point
Hier ist ein Cron-Format, das Ihnen helfen wird
::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.
Hoffe das wird dir helfen :)