Qual é a melhor maneira de executar tarefas agendadas em um ambiente Rails? Script / corredor? Ancinho? Eu gostaria de executar a tarefa a cada poucos minutos.
Qual é a melhor maneira de executar tarefas agendadas em um ambiente Rails? Script / corredor? Ancinho? Eu gostaria de executar a tarefa a cada poucos minutos.
Respostas:
Estou usando a abordagem rake (conforme suportado por heroku )
Com um arquivo chamado lib / tasks / cron.rake ..
task :cron => :environment do
puts "Pulling new requests..."
EdiListener.process_new_messages
puts "done."
end
Para executar a partir da linha de comando, isso é apenas "rake cron". Esse comando pode ser colocado no cron / agendador de tarefas do sistema operacional, conforme desejado.
Atualizar esta é uma pergunta e resposta bastante antigas! Algumas novas informações:
load "#{Rails.root}/lib/tasks/cron.rake"
e rake cron
, mas obtive NameError: variável local indefinida ou método `cron 'para main: Object
:environment
dependência. Temos um aplicativo Rails muito pesado que demora muito para iniciar, nosso Rake é chamado a cada minuto e consome mais recursos iniciando o ambiente Rails que executa a tarefa . Eu adoraria ter um ambiente Rails já iniciado para ser chamado através do cron, deve haver algo entre a abordagem do controlador e a do ambiente rake .
Eu usei o extremamente popular Whenever em projetos que dependem muito de tarefas agendadas, e é ótimo. Ele fornece um bom DSL para definir suas tarefas agendadas em vez de precisar lidar com o formato crontab. No README:
Sempre que é uma gema Ruby, fornece uma sintaxe clara para escrever e implantar tarefas cron.
Exemplo do 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
Em nosso projeto, usamos pela primeira vez sempre que gem, mas enfrentamos alguns problemas.
Em seguida, mudamos para a gema RUFUS SCHEDULER , que acabou sendo muito fácil e confiável para agendar tarefas no Rails.
Nós o usamos para enviar e-mails semanais e diários e até para executar algumas tarefas periódicas de rake ou qualquer outro método.
O código usado é o seguinte:
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 mais: https://github.com/jmettraux/rufus-scheduler
Supondo que suas tarefas não demorem muito para serem concluídas, basta criar um novo controlador com uma ação para cada tarefa. Implemente a lógica da tarefa como código do controlador e, em seguida, configure um cronjob no nível do sistema operacional que use o wget para chamar a URL desse controlador e a ação nos intervalos de tempo apropriados. As vantagens deste método são você:
As tarefas de script / runner e rake são perfeitas para serem executadas como tarefas cron.
Aqui está uma coisa muito importante que você deve lembrar ao executar tarefas cron. Eles provavelmente não serão chamados no diretório raiz do seu aplicativo. Isso significa que todos os seus requisitos para arquivos (ao contrário de bibliotecas) devem ser feitos com o caminho explícito: por exemplo, File.dirname (__ FILE__) + "/ other_file". Isso também significa que você precisa saber como chamá-los explicitamente de outro diretório :-)
Verifique se o seu código suporta a execução de outro diretório com
# 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
Além disso, os trabalhos cron provavelmente não são executados como você, portanto, não dependa de nenhum atalho inserido no .bashrc. Mas isso é apenas uma dica cron padrão ;-)
O problema de quando (e cron) é que ele recarrega o ambiente de trilhos toda vez que é executado, o que é um problema real quando suas tarefas são frequentes ou têm muito trabalho de inicialização a ser feito. Eu tive problemas na produção por causa disso e devo avisá-lo.
O agendador Rufus faz isso por mim ( https://github.com/jmettraux/rufus-scheduler )
Quando tenho trabalhos longos para executar, uso-o com delayed_job ( https://github.com/collectiveidea/delayed_job )
Eu espero que isso ajude!
Sou um grande fã do resque / resque scheduler . Você não pode apenas executar tarefas repetidas do tipo cron, mas também tarefas em horários específicos. A desvantagem é que ele requer um servidor Redis.
Isso é interessante, ninguém mencionou o Sidetiq . É uma boa adição se você já estiver usando o Sidekiq.
O Sidetiq fornece uma API simples para definir trabalhadores recorrentes para o Sidekiq.
Jó terá a seguinte aparência:
class MyWorker
include Sidekiq::Worker
include Sidetiq::Schedulable
recurrence { hourly.minute_of_hour(15, 45) }
def perform
# do stuff ...
end
end
Ambos irão funcionar bem. Eu costumo usar script / runner.
Aqui está um exemplo:
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
Você também pode escrever um script Ruby puro para fazer isso se carregar os arquivos de configuração corretos para se conectar ao seu banco de dados.
Uma coisa a ter em mente se a memória é preciosa é que o script / runner (ou uma tarefa Rake que depende do 'ambiente') carregará todo o ambiente do Rails. Se você apenas precisar inserir alguns registros no banco de dados, isso utilizará a memória que você realmente não precisa. Se você escrever seu próprio script, poderá evitar isso. Ainda não precisei fazer isso, mas estou considerando.
Use Craken (tarefas cron centralizadas em rake)
Eu uso backgroundrb.
http://backgroundrb.rubyforge.org/
Eu o uso para executar tarefas agendadas, bem como tarefas que demoram muito para o relacionamento normal de cliente / servidor.
Aqui está como eu configurei minhas tarefas cron. Eu tenho um para fazer backups diários do banco de dados SQL (usando rake) e outro para expirar o cache uma vez por mês. Qualquer saída é registrada em um arquivo log / cron_log. Meu crontab fica assim:
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
A primeira tarefa do cron faz backups diários do banco de dados. O conteúdo de cron_tasks é o seguinte:
/usr/local/bin/rake db:backup RAILS_ENV=production; date; echo "END OF OUTPUT ----";
A segunda tarefa foi configurada posteriormente e usa script / runner para expirar o cache uma vez por mês (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}"
Eu acho que eu poderia fazer backup do banco de dados de outra maneira, mas até agora funciona para mim :)
Os caminhos para o rake e o ruby podem variar em diferentes servidores. Você pode ver onde eles estão usando:
whereis ruby # -> ruby: /usr/local/bin/ruby
whereis rake # -> rake: /usr/local/bin/rake
Usar algo Sidekiq ou Resque é uma solução muito mais robusta. Ambos suportam a repetição de trabalhos, exclusividade com um bloqueio, monitoramento e programação REDIS.
Lembre-se de que o Resque é um projeto morto (não é mantido ativamente), portanto o Sidekiq é uma alternativa muito melhor. Ele também tem mais desempenho: o Sidekiq executa vários trabalhadores em um único processo multithread enquanto o Resque executa cada trabalhador em um processo separado.
Recentemente, criei alguns trabalhos cron para os projetos nos quais tenho trabalhado.
Achei que a gema Clockwork era muito útil.
require 'clockwork'
module Clockwork
every(10.seconds, 'frequent.job')
end
Você pode até agendar seu trabalho em segundo plano usando esta gema. Para documentação e ajuda adicional, consulte https://github.com/Rykian/clockwork
você pode usar resque
e resque-schedular
gem para criar cron, isso é muito fácil de fazer.
Uma vez eu tive que tomar a mesma decisão e estou muito feliz com essa decisão hoje. Use o resque scheduler porque não apenas um redis separado removerá a carga do seu banco de dados, você também terá acesso a muitos plugins como o resque-web, que fornece uma ótima interface de usuário. À medida que o seu sistema se desenvolve, você terá mais e mais tarefas para agendar e poderá controlá-las a partir de um único local.
Provavelmente, a melhor maneira de fazer isso é usar o rake para escrever as tarefas que você precisa e apenas executá-lo via linha de comando.
Você pode ver um vídeo muito útil em railscasts
Veja também outros recursos:
Não tenho muita certeza, acho que depende da tarefa: quantas vezes executar, quão complicada e quanta comunicação direta com o projeto rails é necessária etc. Acho que se houvesse apenas "One Best Way" para fazer algo , não haveria tantas maneiras diferentes de fazer isso.
No meu último trabalho em um projeto do Rails, precisávamos fazer uma correspondência em lote (convites para pesquisas, não spam), que deveria enviar as mensagens planejadas sempre que o servidor tivesse tempo. Acho que íamos usar as ferramentas daemon para executar as tarefas de rake que eu havia criado.
Infelizmente, nossa empresa teve alguns problemas financeiros e foi "comprada" pelo principal rival para que o projeto nunca fosse concluído, então não sei o que eventualmente teríamos usado.
Eu uso o script para executar o cron, que é a melhor maneira de executar um cron. Aqui está um exemplo para cron,
Abra o CronTab -> sudo crontab -e
E Cole as linhas abaixo:
00 00 * * * wget https: // your_host / some_API_end_point
Aqui está um formato cron, irá ajudá-lo
::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.
Espero que isso ajude você :)