cron으로 스케쥴러 만들기.

2019. 2. 15. 18:12개발/기타

스케쥴러를 추가해야할 일이 있었다. 


근데 요구사항이 미묘했다. 무조건 2주 간격으로 작동해야한다고 한다.


cron은 시각, 날짜, 요일 등을 특정해서 스케쥴을 돌릴 순 있어도, 일정 간격을 지정해서 돌리는 기능은 없는것으로 알고있다.

(단순히 시간마다 한 번, 하루에 한 번, 일주일에 한 번, 달에 한 번 정도는 정할 수 있지만)


즉, 기존에 사용하던 방식이 아니라 다른 방식으로 사용할 필요가 있었다.


2주 간격으로 스케쥴을 진행하려면 여러가지 방법을 채택할 수 있다.




  • 스케쥴 자체를 crontab에서 2주 간격으로 돌린다.
    • 일단 stackoverflow를 찾아보았다.
      • https://serverfault.com/questions/633264/cronjob-run-every-two-weeks-on-saturday-starting-on-this-saturday

    • 내용을 보아, 현 주차가 이번 년도의 몇 번째 주차인지를 받고, 그것을 2로 나눈 나머지가 1일 경우에 스케쥴을 실행하는 방식인 듯 하다.
      괜찮은 방법이지만, 해당 게시글에도 적혀있듯, 한 가지의 엣지케이스가 있다는 것을 알 수 있다. 53주차 -> 1주차로 가는 경우에서 문제가 생길 수 있는 것이다.
      • 정확히는 이해가 되지 않지만.. 내가 이해한 바는 아래와 같다.
         1월 1일인 요일부터 1주차를 시작하는 방식으로 계산하면, 1년은 365일이니까, 1월 1일이었던 요일의 +1요일은 53주차가 생기게 된다. 
         다음 년도의 1월 1일은, 지난 연도의 1월 1일의 +2요일이 되고 그러면 거기서 4일 뒤는 53주차에도, 1주차에도 있게 된다. 즉, 특정 요일 1개 (윤년에는 2개) 는 53주차와 1주차에 다 포함되는 경우가 생기는 것.
      • 이 문제 때문에 (정확하게 파악한건진 모르겠으나...) 해당 방법은 채택하지 않기로 했다.

  • cron 수준에서는 매 주 스케쥴링을 실행하고, 쉘 스크립트에서 격주로 실행될 수 있도록 걸러낸다.
    • 스케쥴러가 돌아가는 서버의 로컬에 flag로 사용할 수 있는 file을 둬서, 해당 파일의 유무로 실행을 결정한다.

나의 경우는 후자의 방법을 사용했는데, 일단 cron에서 주차를 받아올 때, 특정 요일로써 주차를 구분하는건지, 1월 1일인 요일로써 구분하는지를 확실히 알지 못해서 후자를 사용했다. 


#!/bin/bash

mark_file=$HOME/.filename

#check whether the job run last time it is invoked
if [ -e $mark_file ] ; then
rm -f $mark_file
else
touch $mark_file
exit 0
fi

command

이와 같은 형태로 제작했다.


방법이 썩 마음에 들지는 않지만 일단 2주마다 확실히 도는 것은 보장할 수 있을 것이다.

스케쥴러에 문제가 생기는 것을 방지하기 위해 if 조건 안에 마지막 수정 시각 범위를 걸어주고, 스케쥴을 비슷한 시간대에 여러번 실행시키는 로직도 추가하면 좋을 것 같다.