Qual è il modo migliore per eseguire attività pianificate in un ambiente Rails? Script / runner? Rastrello? Vorrei eseguire l'attività ogni pochi minuti.
Qual è il modo migliore per eseguire attività pianificate in un ambiente Rails? Script / runner? Rastrello? Vorrei eseguire l'attività ogni pochi minuti.
Risposte:
Sto usando l'approccio rake (come supportato da heroku )
Con un file chiamato lib / task / cron.rake ..
task :cron => :environment do
puts "Pulling new requests..."
EdiListener.process_new_messages
puts "done."
end
Per eseguire dalla riga di comando, questo è solo "rake cron". Questo comando può quindi essere inserito nel programma di pianificazione cron / task del sistema operativo come desiderato.
Aggiorna questa è piuttosto una vecchia domanda e risposta! Alcune nuove informazioni:
load "#{Rails.root}/lib/tasks/cron.rake"
e rake cron
, ma ho ricevuto NameError: variabile locale non definita o metodo `cron 'per main: Object
:environment
dipendenza. Abbiamo un'applicazione Rails molto pesante che impiega molto tempo ad avviarsi, il nostro Rake viene chiamato ogni minuto e consuma più risorse all'avvio dell'ambiente Rails rispetto all'esecuzione dell'attività . Mi piacerebbe avere un ambiente Rails già avviato per essere chiamato tramite cron, deve essere qualcosa tra l' approccio controller e quello rake .
Ho usato il estremamente popolare Whenever su progetti che dipendono fortemente da attività pianificate, ed è fantastico. Ti dà un bel DSL per definire le tue attività pianificate invece di dover gestire il formato crontab. Dal README:
Ogni volta che è una gemma di Ruby che fornisce una chiara sintassi per la scrittura e la distribuzione di cron job.
Esempio dal 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
Nel nostro progetto abbiamo usato per la prima volta ogni gemma, ma abbiamo affrontato alcuni problemi.
Siamo quindi passati a RUFUS SCHEDULER gioiello , che si è rivelato molto semplice e affidabile per le attività di pianificazione in Rails.
Lo abbiamo usato per l'invio di mail settimanali e giornaliere e anche per l'esecuzione di alcune attività periodiche di rake o di qualsiasi metodo.
Il codice usato in questo è come:
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
Per saperne di più: https://github.com/jmettraux/rufus-scheduler
Supponendo che le attività non richiedano troppo tempo per il completamento, basta creare un nuovo controller con un'azione per ogni attività. Implementare la logica dell'attività come codice controller, quindi impostare un cronjob a livello di sistema operativo che utilizza wget per richiamare l'URL di questo controller e agire agli intervalli di tempo appropriati. I vantaggi di questo metodo sei:
le attività di script / runner e rake vanno perfettamente bene come cron job.
Ecco una cosa molto importante che devi ricordare quando esegui lavori cron. Probabilmente non verranno chiamati dalla directory principale della tua app. Ciò significa che tutti i tuoi requisiti per i file (al contrario delle librerie) devono essere eseguiti con il percorso esplicito: ad esempio File.dirname (__ FILE__) + "/ other_file". Questo significa anche che devi sapere come chiamarli esplicitamente da un'altra directory :-)
Controlla se il tuo codice supporta l'esecuzione da un'altra directory 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
Inoltre, i lavori cron probabilmente non vengono eseguiti come te, quindi non dipendono da alcun collegamento inserito in .bashrc. Ma questo è solo un suggerimento cron standard ;-)
Il problema di quando (e cron) è che ricarica l'ambiente delle rotaie ogni volta che viene eseguito, il che è un vero problema quando le tue attività sono frequenti o hanno molto lavoro di inizializzazione da fare. Ho avuto problemi di produzione a causa di questo e devo avvisarti.
Rufus Scheduler lo fa per me ( https://github.com/jmettraux/rufus-scheduler )
Quando ho lunghi lavori da eseguire, lo uso con delayed_job ( https://github.com/collectiveidea/delayed_job )
Spero che aiuti!
Questo è interessante, nessuno ha menzionato il Sidetiq . È una bella aggiunta se stai già utilizzando Sidekiq.
Sidetiq fornisce una semplice API per la definizione di lavoratori ricorrenti per Sidekiq.
Il lavoro sarà simile al seguente:
class MyWorker
include Sidekiq::Worker
include Sidetiq::Schedulable
recurrence { hourly.minute_of_hour(15, 45) }
def perform
# do stuff ...
end
end
Entrambi funzioneranno bene. Di solito uso script / runner.
Ecco un esempio:
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
Puoi anche scrivere uno script pure-Ruby per farlo se carichi i file di configurazione giusti per connetterti al tuo database.
Una cosa da tenere a mente se la memoria è preziosa è che lo script / runner (o un'attività Rake che dipende dall '"ambiente") caricherà l'intero ambiente Rails. Se hai solo bisogno di inserire alcuni record nel database, questo utilizzerà la memoria che non è necessario. Se scrivi la tua sceneggiatura, puoi evitarlo. In realtà non ho ancora avuto bisogno di farlo, ma lo sto prendendo in considerazione.
Usa Craken (processi cron rake centric)
Uso backgroundrb.
http://backgroundrb.rubyforge.org/
Lo uso per eseguire attività pianificate e attività che richiedono troppo tempo per la normale relazione client / server.
Ecco come ho impostato i miei compiti cron. Ne ho uno per fare backup giornalieri del database SQL (usando rake) e un altro per far scadere la cache una volta al mese. Qualsiasi output viene registrato in un file log / cron_log. Il mio crontab è simile al seguente:
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 prima attività cron esegue backup giornalieri del db. I contenuti di cron_tasks sono i seguenti:
/usr/local/bin/rake db:backup RAILS_ENV=production; date; echo "END OF OUTPUT ----";
La seconda attività è stata configurata in un secondo momento e utilizza script / runner per far scadere la cache una volta al mese (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}"
Immagino di poter fare il backup del database in qualche altro modo, ma finora funziona per me :)
I percorsi per rastrellare e ruby possono variare su server diversi. Puoi vedere dove sono usando:
whereis ruby # -> ruby: /usr/local/bin/ruby
whereis rake # -> rake: /usr/local/bin/rake
Usare qualcosa come Sidekiq o Resque è una soluzione molto più solida. Supportano entrambi i tentativi di lavoro, l'esclusività con un blocco REDIS, il monitoraggio e la pianificazione.
Tieni presente che Resque è un progetto morto (non attivamente mantenuto), quindi Sidekiq è un'alternativa decisamente migliore. È anche più performante: Sidekiq esegue diversi lavoratori su un singolo processo multithread mentre Resque esegue ciascun lavoratore in un processo separato.
Di recente ho creato alcuni lavori cron per i progetti a cui ho lavorato.
Ho scoperto che la gemma Clockwork è molto utile.
require 'clockwork'
module Clockwork
every(10.seconds, 'frequent.job')
end
Puoi anche pianificare il tuo lavoro in background usando questo gioiello. Per la documentazione e ulteriore assistenza, consultare https://github.com/Rykian/clockwork
puoi usare resque
eresque-schedular
gem per creare cron, questo è molto facile da fare.
Una volta ho dovuto prendere la stessa decisione e sono davvero contento di quella decisione oggi. Usa resque scheduler perché non solo un redis separato eliminerà il carico dal tuo db, ma avrai anche accesso a molti plugin come resque-web che fornisce una grande interfaccia utente. Man mano che il tuo sistema si sviluppa, avrai sempre più attività da pianificare in modo da poterle controllare da un'unica posizione.
Probabilmente il modo migliore per farlo è usare rake per scrivere le attività che ti servono e semplicemente eseguirlo tramite riga di comando.
Puoi vedere un molto utile video sui railscast
Dai un'occhiata anche a queste altre risorse:
Ho usato la gemma dell'orologio e funziona abbastanza bene per me. C'è anche una clockworkd
gemma che consente a uno script di essere eseguito come demone.
Non ne sono davvero sicuro, immagino che dipenda dal compito: quanto spesso eseguire, quanto complicato e quanta comunicazione diretta con il progetto Rails è necessario ecc. Immagino che ci fosse solo "One Best Way" per fare qualcosa , non ci sarebbero tanti modi diversi per farlo.
Nel mio ultimo lavoro in un progetto Rails, dovevamo creare un mailer di inviti batch (inviti al sondaggio, non spamming) che dovrebbe inviare i messaggi programmati ogni volta che il server ha avuto tempo. Penso che avremmo usato gli strumenti daemon per eseguire le attività di rake che avevo creato.
Sfortunatamente, la nostra azienda ha avuto alcuni problemi di denaro ed è stata "acquistata" dal principale rivale, quindi il progetto non è mai stato completato, quindi non so cosa alla fine avremmo usato.
Uso lo script per eseguire cron, questo è il modo migliore per eseguire un cron. Ecco qualche esempio di cron,
Apri CronTab -> sudo crontab -e
E incolla le linee di soffietto:
00 00 * * * wget https: // your_host / some_API_end_point
Ecco un formato cron, ti aiuterà
::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.
Spero che questo ti possa aiutare :)