레일을위한 크론 작업 : 모범 사례?


295

Rails 환경에서 예약 된 작업을 실행하는 가장 좋은 방법은 무엇입니까? 스크립트 / 러너? 갈퀴? 몇 분마다 작업을 실행하고 싶습니다.


149
Google에서 여기 온 사람들은 더 나은 접근 방법을 위해 허용 된 답변 이상의 것을 살펴보십시오.
jrdioko

4
언제나 대답은 받아 들인 대답보다 합리적으로 보입니다. 이것은 오래된 해킹입니다.
Rob

2
또한 최소한 하나의 답변에 특정 보석이 설치되어 있다고 가정하십시오.
Tass

좋은 사례가 여기에 요약의 커플 (나는 것으로 밝혀 찾았는지) wisecashhq.com/blog/writing-reliable-cron-jobs
의 Thibaut 바레

많은 경우에 크론 작업은 나쁜 냄새입니다. sidekiq / resque (또는 다른 백그라운드 워커)를 통해 스케줄러를 작성하거나 데몬 (기능 및 모니터링이 적은)을 작성하십시오. 크론 작업에는 최소한 몇 가지 나쁜 점이 있습니다. 1) 하나의 인스턴스에 대한 잠금은 고통입니다. 2) 모니터링을 쉽게 수행 할 수 없습니다. 3) 예외 처리는 수동으로 다시 작성해야합니다. 4) 다시 시작하기 쉽지 않다. 5) 배경 노동자들이 쉽게 해결할 수있는 위의 모든 문제.
Dmitry Polushkin

답변:


110

레이크 접근 방식을 사용하고 있습니다 ( heroku 지원 )

lib / tasks / cron.rake 파일이 있습니다.

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

명령 행에서 실행하려면 "rake cron"입니다. 그런 다음이 명령을 원하는대로 운영 체제 cron / 작업 스케줄러에 넣을 수 있습니다.

이것은 오래된 질문과 답변입니다 업데이트 ! 몇 가지 새로운 정보 :

  • 내가 참조한 heroku cron 서비스는 이후 Heroku Scheduler 로 대체되었습니다.
  • 빈번한 작업 (특히 Rails 환경 시작 비용을 피하려는 경우)에서 선호하는 접근 방식은 시스템 크론을 사용하여 (a) 백그라운드에서 필요한 작업을 호출하기 위해 보안 / 개인 웹 후크 API를 찌르는 스크립트를 호출하는 것입니다. 또는 (b) 선택한 대기열 시스템에서 작업을 직접 대기열에 추가

이 경우 cron 항목은 무엇이어야하므로 OS가 레이크 작업의 올바른 경로를 알고 있습니까?
jrdioko

13
NB : 요즘에는 언제든 사용하고 있지만 (Jim Garvin의 답변 참조) 레이크 작업을 실행하기위한 원시 크론 항목은 다음과 같습니다. 30 4 * * * / bin / bash -l -c 'cd / opt / railsapp && RAILS_ENV = 생산 레이크 크론-자동 '
tardate

1
콘솔에서 이것을 어떻게 호출합니까? 내가 그랬어 load "#{Rails.root}/lib/tasks/cron.rake"하고 rake cron있지만, 나가서 설명하자면 NameError 가지고 : 정의되지 않은 지역 변수 또는 주에 대한 방법`크론 ': 개체
B 세븐

3
이 접근법의 문제점은 :environment종속성입니다. 우리는 시작하는데 시간이 오래 걸리는 매우 무거운 Rails 애플리케이션을 가지고 있습니다. Rake는 1 분마다 호출되며 작업 을 실행하는 Rails 환경 을 시작하는 데 더 많은 리소스를 소비 합니다 . 나는 이미 cron을 통해 호출되도록 Rails 환경을 시작 하고 싶습니다 . 컨트롤러 접근과 레이크 환경 사이에 무언가 있어야합니다 .
fguillen

이 작업의 기간은 얼마입니까? if 조건을 사용하고 있습니다. 이것이 얼마나 정기적으로 실행되는지 알고 싶습니다. heroku 웹 사이트에서 이에 대한 정보를 찾을 수 없습니다.
Shubham Chaudhary

254

나는 예약 된 작업에 크게 의존하는 프로젝트를 할 때마다 매우 인기가 많았 습니다. crontab 형식을 처리하지 않고 예약 된 작업을 정의 할 수있는 훌륭한 DSL을 제공합니다. 읽어보기에서 :

cron 작업을 작성하고 배포하기위한 명확한 구문을 제공하는 Ruby gem 일 때마다.

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

22
1 분마다 실행되면 매번 환경이 다시 시작되므로 비용이 많이들 수 있습니다. github.com/ssoroka/scheduler_daemon 은 이것을 피하는 것 같습니다 .
lulalala

3
버전 관리 시스템의 크론 구성을 유지 한
brittohalloran

3
이것이 최선의 해결책이라고 생각합니다. 레일을 사용하는 경우 모든 것을 레일에 쓰는 것이 좋습니다. 이 방법을 사용하면 서버를 변경할 때 cron 작업을 잊어 버릴 수 있으며 앱과 함께 이동합니다.
Adrian Matteo

도움이 될 때마다 좋은 Railscast 가 있습니다 (이전의 무료 버전도 있습니다).
aceofbassgreg

@Tony, 기본적으로 cron 작업을 작성하기위한 도메인 특정 언어입니다. 레일 서버에서 일반 크론 구문으로 컴파일되며 크론은 지정한 작업 (일반적으로 레일 러너를 통해)을 실행합니다.
그렉

19

프로젝트에서 우리는 보석을 사용할 때마다 처음 사용했지만 몇 가지 문제에 직면했습니다.

그런 다음 RUFUS SCHEDULER gem으로 전환하여 Rails에서 작업을 예약하는 데 매우 쉽고 신뢰할 수있는 것으로 나타났습니다.

우리는 매주 및 매일 메일을 보내거나주기적인 레이크 작업이나 방법을 실행하는 데 사용했습니다.

이것에 사용되는 코드는 다음과 같습니다

    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

자세한 내용은 https://github.com/jmettraux/rufus-scheduler


1
간단한 루비 프로젝트 또는 풀 레일 앱 모두에 사용했기 때문에 루푸에게 적합합니다.
Paulo Fidalgo 2013 년

8
언제든 발생한 문제에 대해 좀 더 구체적으로 설명해 주시겠습니까?
Duke

가장 위대한 답변
Darlan Dieterich

17

작업을 완료하는 데 시간이 오래 걸리지 않는다고 가정하면 각 작업에 대한 작업으로 새 컨트롤러를 만드십시오. 태스크의 논리를 컨트롤러 코드로 구현 한 다음 wget을 사용하여이 컨트롤러의 URL을 호출하고 적절한 시간 간격으로 조치를 수행하는 OS 레벨에서 cronjob을 설정하십시오. 이 방법의 장점은 다음과 같습니다.

  1. 일반 컨트롤러처럼 모든 Rails 객체에 완전히 액세스 할 수 있습니다.
  2. 정상적인 행동을하는 것처럼 개발하고 테스트 할 수 있습니다.
  3. 간단한 웹 페이지에서 작업 adhoc을 호출 할 수도 있습니다.
  4. 추가 루비 / 레일 프로세스를 실행하여 더 이상 메모리를 사용하지 마십시오.

12
다른 사람이이 작업에 액세스하지 못하게하는 방법은 무엇입니까? CPU를 가져 와서 호출하는 작업이 자주 발생하면 문제가 발생합니다.
sarunw

44
나는 이것이 얼마 전인 것을 알고 있지만 이것은 더 이상 cron 작업을 수행하는 가장 좋은 방법은 아닙니다. Rails 환경에 액세스 할 수있는 다른 방법이 많을 때 웹 인터페이스를 통해 인터페이스가 실제로 나타내는 것을 위반하는 이유는 무엇입니까?
Matchu

6
"작업을 완료하는 데 너무 오래 걸리지 않는다"고 가정하는 자격은 거대합니다. 작업이 매우 빠른 경우뿐만 아니라 더 일반적으로 유용한 접근 방식을 사용하는 것이 낫지 않습니까? 이렇게하면 다른 접근 방식을 사용하여이 작업 또는 해당 작업을 다시 작성해야하는지 지속적으로 재평가하지 않아도됩니다.
iconoclast

77
이 오래된 질문은 "rails cron"에 대한 최고의 Google 결과입니다. 이 답변은 최선의 접근 방식과는 거리가 멀다. 더 건전한 제안은 다른 답변을 참조하십시오.
Jim Garvin

2
가장 좋은 방법은 아닙니다. REST 서비스를 호출하지 않고 cron 작업을 통해 Rails env에 액세스하는 다른 많은 방법이 있습니다. 레이크 접근 방식은 더 확실히
샤인

10

스크립트 / 러너 및 레이크 작업은 크론 작업으로 실행하기에 완벽합니다.

cron 작업을 실행할 때 반드시 기억해야 할 중요한 사항이 있습니다. 아마도 앱의 루트 디렉토리에서 호출되지 않을 것입니다. 즉, 파일에 대한 모든 요구 사항 (라이브러리와 달리)은 명시 적 경로 (예 : File.dirname (__ FILE__) + "/ other_file")를 사용하여 수행해야합니다. 이것은 또한 다른 디렉토리에서 명시 적으로 호출하는 방법을 알아야한다는 것을 의미합니다 :-)

코드가 다른 디렉토리에서 실행될 수 있는지 확인하십시오.

# 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

또한 크론 작업은 아마도 실행되지 않을 것이므로 .bashrc에 넣은 바로 가기에 의존하지 마십시오. 그러나 그것은 단지 표준 cron 팁입니다 ;-)


작업을 모든 사용자로 실행할 수 있지만 (원하는 사용자의 crontab 항목을 설정하기 만하면) 프로파일 및 로그인 스크립트가 실행되지 않고 홈 디렉토리에서 시작되지 않는 것이 올바른 것입니다. 따라서 @ luke-franci의 의견에 표시된 것처럼 "cd"로 명령을 시작하는 것이 일반적입니다.
Tom Wilson

10

언제나 (그리고 cron)의 문제는 그것이 실행될 때마다 레일 환경을 다시로드한다는 것입니다. 이것은 작업이 빈번하거나 초기화 작업이 많이 필요한 실제 문제입니다. 이로 인해 생산에 문제가 있었고 경고해야합니다.

Rufus 스케줄러가 나를 위해합니다 ( https://github.com/jmettraux/rufus-scheduler )

실행할 작업이 길면 delayed_job ( https://github.com/collectiveidea/delayed_job ) 과 함께 사용합니다.

이게 도움이 되길 바란다!


10

나는 resque / resque 스케줄러 의 큰 팬입니다 . cron과 유사한 반복 작업뿐만 아니라 특정 시간에 작업도 실행할 수 있습니다. 단점은 Redis 서버가 필요하다는 것입니다.


10

아무도 Sidetiq을 언급하지 않은 것이 흥미 롭습니다 . Sidekiq을 이미 사용하고 있다면 좋은 추가 기능입니다.

Sidetiq은 Sidekiq의 반복 작업자를 정의하기위한 간단한 API를 제공합니다.

직업은 다음과 같습니다.

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

  recurrence { hourly.minute_of_hour(15, 45) }

  def perform
    # do stuff ...
  end
end

8

둘 다 잘 작동합니다. 나는 보통 스크립트 / 러너를 사용합니다.

예를 들면 다음과 같습니다.

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

데이터베이스에 연결하기 위해 올바른 구성 파일을로드하는 경우 순수 Ruby 스크립트를 작성할 수도 있습니다.

메모리가 소중한 경우 명심해야 할 것은 스크립트 / 런너 (또는 '환경'에 의존하는 레이크 작업)가 전체 Rails 환경을로드한다는 것입니다. 데이터베이스에 일부 레코드 만 삽입하면 실제로 필요하지 않은 메모리가 사용됩니다. 자신의 스크립트를 작성하면이를 피할 수 있습니다. 실제로이 작업을 수행 할 필요는 없었지만 고려하고 있습니다.


8

크랙 사용 (레이크 중심 크론 작업)


1
cron 작업을 작성하는 것은 매우 어렵습니다. 보석을 다운로드하는 것이 좋습니다
f0ster

1
어렵지는 않지만 git에 저장하고 배포 할 때 항상 최신 상태를 유지하는 것은 팀에서 일할 때 큰 이점입니다.
Thibaut Barrère


3

cron 작업을 설정하는 방법은 다음과 같습니다. 하나는 SQL 데이터베이스를 매일 백업하고 (레이크를 사용하여) 한 달에 한 번 캐시를 만료시키는 백업이 있습니다. 모든 출력은 파일 log / cron_log에 기록됩니다. 내 crontab은 다음과 같습니다.

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

첫 번째 cron 태스크는 매일 DB 백업을 수행합니다. cron_tasks의 내용은 다음과 같습니다.

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

두 번째 작업은 나중에 설정되었으며 스크립트 / 런너를 사용하여 한 달에 한 번 캐시를 만료합니다 (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}"

나는 다른 방법으로 데이터베이스를 백업 할 수 있다고 생각하지만 지금까지 그것은 나를 위해 작동 :)

갈퀴와 루비 의 경로 는 서버마다 다를 수 있습니다. 다음을 사용하여 위치를 확인할 수 있습니다.

whereis ruby # -> ruby: /usr/local/bin/ruby
whereis rake # -> rake: /usr/local/bin/rake

3

Sidekiq 또는 Resque를 사용하는 것이 훨씬 강력한 솔루션입니다. 두 가지 모두 작업 재시도, REDIS 잠금을 통한 독점 성, 모니터링 및 스케줄링을 지원합니다.

Resque는 죽은 프로젝트 (활동적으로 유지 관리되지 않음)이므로 Sidekiq가 더 나은 대안입니다. 또한 Sidekiq는 단일 멀티 스레드 프로세스에서 여러 작업자를 실행하고 Resque는 각 작업자를 별도의 프로세스로 실행합니다.


정답입니다. 등을 조절하고 제한, 작업의 수를 실패 또는 예약 실행 독특한 노동자, 쉽게 다시 시작 잠금 : 그 sidekiq 또는 resque가 무슨 일이 일어나고 있는지 모니터링을위한 웹 인터페이스를 같이 제공하고, 좋은 기능에 대해 잊을 수 많은
드미트리을 Polushkin

3

최근에 내가 작업 한 프로젝트에 대한 일부 크론 작업을 만들었습니다.

보석 시계가 매우 유용 하다는 것을 알았습니다 .

require 'clockwork'

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

이 보석을 사용하여 백그라운드 작업을 예약 할 수도 있습니다. 설명서 및 추가 도움말은 https://github.com/Rykian/clockwork 를 참조 하십시오.



2

일단 같은 결정을 내려야한다면 오늘 그 결정에 정말 만족합니다. 별도의 redis가 db에서로드를 가져갈뿐만 아니라 훌륭한 사용자 인터페이스를 제공하는 resque-web과 같은 많은 플러그인에 액세스 할 수 있기 때문에 resque scheduler를 사용하십시오 . 시스템이 개발됨에 따라 점점 더 많은 작업을 예약 할 수 있으므로 한 곳에서 제어 할 수 있습니다.



1

나는 시계 보석을 사용 했고 그것은 나를 위해 아주 잘 작동합니다. 또한이 clockworkd스크립트는 데몬으로 실행할 수 있습니다 보석.


0

정말 있는지, 나는 그것이 작업에 따라 생각하고 있지 않다 : 실행하는 방법을 자주, 많이 복잡 얼마나 직접 통신 방법은 프로젝트가 바로이 있다면 등 같아요 필요한 레일과 함께 "한 최선의 방법" 뭔가를 할 수 그렇게하는 방법은 그리 많지 않을 것입니다.

Rails 프로젝트의 마지막 작업에서 서버가있을 때마다 계획된 메일을 보내야하는 일괄 초대 메일러 (스팸 메일이 아닌 설문 초대)를 만들어야했습니다. 우리는 데몬 툴 을 사용 하여 내가 만든 레이크 작업을 실행할 것이라고 생각 합니다.

불행히도, 우리 회사는 돈 문제가 있었고 주요 라이벌이 "매입"하여 프로젝트가 완료되지 않았으므로 결국 우리가 무엇을 사용했는지 알 수 없습니다.


0

스크립트를 사용하여 cron을 실행하십시오. 이것이 cron을 실행하는 가장 좋은 방법입니다. 다음은 cron의 예입니다.

CronTab 열기-> sudo crontab -e

그리고 벨로우 라인 붙여 넣기 :

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

여기에 cron 형식이 있습니다.

::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. 

희망이 당신을 도울 것입니다 :)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.