티스토리 뷰

해당 글은 https://blog.naver.com/kbs4674/221197430824 로 부터 게시글이 이전되었습니다.

 

제 홈페이지 같은 경우는 Paranoia의 기능 중, 만약에 게시글을 삭제되어도 겉으론 삭제된 척, 실제론 삭제가 안되게(DB상에 남아있게) 보존을 해놓는 기능이 있습니다.

 

이미 한번 삭제되었던 게시글 (보라색 제목으로 표기)

하지만 이렇게 이미 한번 삭제된 게시글이 계속 영구적으로 남겨놓으면 좋겠지만.. 계속 쌓이는 더미데이터에 대해 굳이 가지고 있을 필요가 없어, n개월 후에 삭제된 게시글이 자동으로 완전히 삭제되는 방식을 적용하기위해 lib/task과 whenever Gem에 대해 소개하고자 합니다.

 

참고로 whenever Gem은 레일즈 Active Job의 기술이 쓰이는 Gem 중 하나로서, 홈페이지가 돌아가는 와중에 뒤에서 다른 작업을 동시에 하는 Gem입니다. (즉, Rails 서버를 돌림과 동시에 n시간 단위로 게시글이 삭제되는 작업도 진행되는 것이죠.)

whenever Gem은 리눅스의 Cron Job 기능과 유사한 기능이라고 이해하시면 되겠습니다.

 

이와 별개로, Background 작업이 이루어 지긴 하나, 스케쥴링(예약된 시간) 작업 방식이 아닌 '먼저 들어온 순서대로 작업이 진행되는 방식'에 대해서도 방법이 존재합니다.

해당 방법에 대해서는 사이드킥(Sidekiq) Gem 부분을 참고해주시면 되겠습니다.

 

 

  • lib/tasks 개념

 

whenever Gem을 설명하기 전, 짚고 넘어갈 개념에 대해서 설명해보겠습니다.

레일즈 디렉토리를 보시면 'lib'이라는 디렉토리를 한번쯤은 보고 그냥 넘어가셨을 겁니다.

처음에는 저도 저 기능에 대해서 '아 저런게 있구나' 하고 그냥 넘어가곤 하다가, 이번에서야 저 기능이 뭔지 알게되었습니다.

 

 lib/task  는 사용자가  rake:...  명령어만 입력하면 tasks폴더 내에 있는 파일이 작동하게 되는데, 파일속에 사용자가 미리 입력해둔 명령어가 실행이 됩니다.

 활용 예시  이미 한번 지워진 게시물을 아예 삭제시킨다 / 사람들에게 이메일을 보낸다 / 정해진 시간 마다 크롤링(정보 수집)을 한다. 

 

 

  • lib/tasks 기능 활용 : 크롤링

이번 실습 에시로서는 크롤링을 활용하여 https://www.wpws.kr/hangang/ 사이트에서 보여지는 한강 온도에 대해 크롤링을 적용시켜보겠습니다.

 

1. 터미널에 다음 명령어를 입력해줍니다.

rails g task [task 파일명] [시행명령 이름]
rails g task crawl han_gang_temp

 

2. 위 명령어를 입력하면  lib/tasks  디렉토리에  posts.rake  라는 파일이 생성된 것을 확인하실 수 있습니다.

해당 파일로 이동합니다.

 

3.  lib/tasks/posts.rake  에 다음 내용을 입력합니다.

 주의  Paranoia Gem에 적용 기준 코드입니다.

## lib/tasks/crawl.rake

namespace :crawl do
  task han_gang_temp: :environment do
    doc = Nokogiri::HTML(open("https://www.wpws.kr/hangang/"))
    @hanGangTemp = doc.css("#temp").text
    puts "현재 한강 온도는 #{@hanGangTemp} 입니다."
  end
end

 

4. 잘 돌아가는지 확인해볼까요?

rake crawl:han_gang_temp

 

 

  • 정해진 시간마다 삭제 : whenever

이제 '크롤링' 이라는 Trigger 조건은 만족했습니다.

하지만 저희가 매번  rake crawl:han_gang_temp  명령어를 치기에는 귀찮고, 버겁죠.

 

이런 기능을 자동으로 수행해주는 Gem이 있는데, Whenever Gem에 대한 사용설명을 하겠습니다.

 참고  whenever Gem은 레일즈 서버가 꺼진 상태에서도 작업이 수행됩니다.

 

1.  Gemfile  에 다음 내용을 입력해주세요.

gem 'whenever'

그리고 터미널에 아래 명령어를 입력해서 Gem을 설치합니다.

bundle install

 

2. 프로젝트 루트 위치(app, config, db, lib, bin, Gemfile 등등 디렉토리 및 파일이 있는 위치)에서 다음 명령어를 입력해줍니다.

wheneverize .

위 명령어를 입력하면  config  디렉토리에  schedule.rb  라는 파일이 생성된 것을 확인하실 수 있습니다.

 

3.  scheulde.rb  파일을 열람하면 다음과 같은 구조로 되어있습니다.

# Use this file to easily define all of your cron jobs.
#
# It's helpful, but not entirely necessary to understand cron before proceeding.
# http://en.wikipedia.org/wiki/Cron
 
# Example:
#
# set :output, "/path/to/my/cron_log.log"
#
# every 4.minutes do
#   command "..."
#   runner "..."
#   rake "..."
# end
#
# every 4.days do
#   runner "AnotherModel.prune_old_records"
# end
 
# Learn more: http://github.com/javan/whenever

친절하게도 기능의 대부분이 미리 입력되어 있고, 전체가 주석처리가 되어 있음을 확인할 수 있습니다.

 

 참고  각 명령어별 성격

1) command : bash 터미널에 입력될 명령어

command "touch hello"

 

2) runner : Rails Console에 입력될 명령어

TestJob.perform_later()

 

3) rake : lib/tasks 파일을 실행시키는 트리거 명령어

rake "crawl:job"

 

 

4. 현재  schedule.rb  를 그대로 쓰기엔 한 가지 문제점이 있는데요, 한국 현지 시간 기준에 맞지 않게 작업이 수행된다는 점 입니다.

 

whenever Gem에서  config/schedule.rb  에 적어낸 작업 수행 시간 기준은 기본적으로 OS에 설정된 시간(기본:UTC+0, 영국 표준시) 시간을 따릅니다. 하지만 저희가 원하는건 한국 표준 시, 즉 UTC +9 입니다.

사전에  config/application.rb  에 Local 국가를 설정했더라도  config/schedule.rb  에서는 서버의 시간(UTC+0)을 따릅니다.

 

저희는 서버의 시간을 한국 표준시로 설정해보겠습니다.

 주의  Rails 프로젝트 내 코드 중 SQL문이 있을 경우, 해당 Query에 영향을 끼칩니다.

 참고  현재 과정은 꼭 안거쳐도 됩니다만, 후에  schedule.rb  파일에서 시간 설정 시 영국 표준시 기준을 따르다보니 +9시를 고려해서 설계해줘야 합니다.

 

1) 터미널에 아래의 명령어를 입력해서 서버 시간을 한국으로 설정합니다.

## [Ubuntu] 서버의 Timezone을 한국(UTC+9)으로 바꾸는 명령어

sudo ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime

 

2) 터미널에 date 를 입력해서 서버 시간이 한국 표준시로 잘 설정됐는지 확인합니다.

 

3) 서버를 재부팅 해줍니다.

sudo reboot

 

4. 이번 설명에서는 '1분 간격으로  rake crawl:han_gang_temp  명령어가 자동으로 입력' 되게 설정해보겠습니다.

방법은 간단하게 아래와 같이 입력하시면 됩니다.

## config/schedule.rb
 
every 1.minutes do
#   command "/usr/bin/some_great_command"
#   runner "..."
    rake "crawl:han_gang_temp", :environment => "[환경]"
end

환경에 대한 확인법은, 터미널에서 서버를 키면 확인이 가능합니다.

 

 

5. 보통은 다들 development 모드에서 확인을 하고있을겁니다.

이 전 과정의 코드를 다음과 같이 살짝 수정해주세요. (Environment 기입)

## config/schedule.rb
 
every 1.minutes do
#   command "/usr/bin/some_great_command"
#   runner "..."
    rake "crawl:han_gang_temp", :environment => "development"
end

 


Whenever Gem 좀 더 알아보기

 

1. whenever Gem은 시간 단위를 '분(minutes)' 이상으로 지원을 합니다.

 

2. rake 명령어를 2개 이상 적용하고 싶다면 rake 내 따옴표 안에 다음과 같이 써내면 됩니다.

every 1.minutes do
#   command "/usr/bin/some_great_command"
#   runner "..."
    rake "crawl:han_gang_temp; crawl:notice", :environment => "development"
end

 참고  위 설정은 crawl:han_gang_temp 작업과 crawl_notice 작업을 동시에 수행함을 의미함.

 

3. 특정 시간에 명령어를 작동시키고 싶다면 아래와 같이 표현해주면 됩니다.

## config/schedule.rb

...
every :day, at: '5:10 am' do
    ...
end

 서버시간 UTC+9, 한국 기준  매일 오전 5시 10분에 작업을 수행

 서버시간 UTC+0, 한국 기준  매일 오후 2시 10분에 작업을 수행

 

4. 특정 시간에 명령어를 작동시키고 싶다면

## config/schedule.rb

...
 
every :day, at: ['4:30 am', '6:00 pm'] do
    ...
end

 서버시간 UTC+9, 한국 기준  매일 오전 4시 30분, 오후 6시에 작업을 수행

 서버시간 UTC+0, 한국 기준  매일 오후 1시 30분, 오전 4시에 작업을 수행

 

6. crontab 규칙으로도 scheduler 실행이 가능합니다.

 참고  cronjob 규칙

## config/schedule.rb
## 매일 13분 간격으로 작업 수행
...
 
every '*/13 3-5 * * *' do
    ...
end

 서버시간 UTC+9, 한국 기준  매일 3시~5시 사이에 13분마다 작업을 수행

 서버시간 UTC+0, 한국 기준  매일 12시~14시 사이에 13분마다 작업을 수행


6.  /(자기 프로젝트)  로 꼭 이동하신 후, 터미널에 다음 명령어들을 순서대로 입력합니다.

whenever --update-crontab
# => [write] crontab file updated

 schedule.rb  파일이 수정이 되었을 경우, 위 명령어를 항상 쳐주셔야 합니다.

위 명령어를 입력 후,  [write] crontab file updated  메세지가 뜨면 합격입니다.

위 명령어를 입력 시,  schedule.rb  파일을 활성화가 됩니다.

 

 

CronJob이 자기가 설정한대로 잘 적용되었는지 확인을 하고싶을 경우 아래와 같이 whenever을 입력해주세요.

## :environment => "development" 인 경우
 
whenever
# => * * * * * /bin/bash -l -c 'cd /home/ec2-user/knu && RAILS_ENV=development bundle exec rake rake posts:delete_all_post_1year --silent'
 
## [message] Above is your schedule file converted to cron syntax; your crontab file was not updated.
## [message] Run `whenever --help' for more options.

 

 

  • 최신화 & whenever 재 시작
## crontab 재시작
sudo service cron restart

## 스케쥴러(config/schedule.rb)를 Cronjob에 최신화
whenever --update-crontab

## 스케쥴러 Job 확인
whenever

 

 

  • whenever 멈추기 (Stop) / 멈춤 상태에서 Crontab 가동을 원할 시

1) 작동→멈춤

whenever -c

 

2) 멈춤→작동

whenever --update-crontab

 

 

  •  이슈  config/schedule.rb 내에서 rake 미동작

 config/schedule.rb  에서 command, runner은 잘 작동되지만 rake가 안되는 이슈가 발생할 수도 있습니다.

그런데 또 bash 터미널에서 rake를 실행하면 잘 되고...

 

이는 기존의 rake 명령어가 실행되는 PATH가 서로 다르기 때문일 수 있습니다.

gem which rake : config/schedule.rb 에서 바라보는 PATH, which rake : 일반 터미널에서 바라보는 PATH

 gem which rake  같은 경우는  config/schedule.rb  에서 바라보는 PATH인 반면,

 which rake  는 일반적인 터미널(bash 등)에서 바라보는 PATH입니다.

 

또 whenever Gem에서는 기본적으로 -l 플래그가 붙어져서 실행이 되는데, 이는 rake PATH가 서로 다른 상황 속에서 문제를 발생시킵니다.

 

 자료 출처  stackoverflow

 

How can i set ruby version in cron job? · Issue #325 · javan/whenever

My schedule.rb : set :output, 'log/cron.log' set :job_template, "/bin/bash -c \":job\"" set :environment, :development job_type :runner, "cd :path && script/rails runner -e :environment ':task' :ou...

github.com

 

해결방법은   config/schedule.rb  파일 내에 아래 내용을 추가하는겁니다.

set :job_template, nil

whenever 공식문서에 언급된 설명

 

  •  이슈  Heroku 오류 발생

Heroku에서 whenever Gem, 즉 Crontab을 실행하려 하면 위와같이 에러가 나옵니다.

이를 해결하기 위해서는 Heroku에서 add-on을 깔아줘야 하는데요,

 

1. Heroku Scheduler[클릭] 라는 Add-on을 설치해주세요.

 

정말 감사하게도 Scheduler Add-on은 무료로 제공되는 헤로쿠 모듈입니다.

 

2. Heroku Scheduler 설정 페이지[클릭]로 이동해주세요.

그리고 Add new job 버튼을 클릭해주세요.

 

3. 어느 시간 때, 어떤 Cron Job 명령어를 실행시킬지 설정을 하시면 됩니다.

 참고 1  Heroku의 Cron Job 시간 설정은 다음과 같이만 설정할 수 있습니다 : every 10 minutes, every hour, every day

 참고 2  저같은 경우, 매 10분 마다 크롤링 작업을 해야해서, 다음과 같이 설정을 해줬습니다.

 참고 3  위에 입력된 rake 명령어는 어디까지나 제 기준입니다, 여러분들 기준에 맞는 명령어를 쳐주세요!

 참고 4  Heroku Scheduler에서 설정하는 시간은 영국 표준 시 기준(UTC +0)입니다.

 

4. 설정이 끝나고, SAVE Job을 해주면 Cron Job이 리스트에 올라갑니다.

 

5. DB 기록을 확인해보니 데이터가 무사히 가져오는게 확인됩니다!

 

 

  • Scheduler Job을 활용한 기능

1. scheduler Job을 활용한 자동 로그파일 백업 및 오래된 파일 삭제

 

 

  • 자료 참고

1. Stackoverflow - 삭제 트리거 적용하기

2. Github - Whenever Gem

3. whenever Gem에 대한 사용설명

4. Heroku에서 Crontab 사용법

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함