Crontab을 이용한 스케쥴링 API 운영하기

업데이트:

개념

소프트웨어 유틸리티 cron은 유닉스 계열 컴퓨터 운영 체제의 시간 기반 잡 스케줄러입니다. 소프트웨어 환경을 설정하고 관리하는 사람들은 작업을 고정된 시간, 날짜, 간격에 주기적으로 실행할 수 있도록 스케줄링하기 위해 cron을 사용합니다. Linux 운영체제에서는 cron방식을 이용해 다양한 스케쥴링을 관리해주는 crontab을 제공하고 있습니다. cron에 대한 사용방법이나, 문법, 자세한 내용은 이 문서를 참조하시면 될 것 같습니다!

의사 결정

서버를 운영하다 보니, 주기적으로 특정 API를 실행해야 할 일이 생겼습니다. node-schedulernode-cron라이브러리를 사용할 수 있었지만, 사용하지 않았습니다. 가장 큰 이유는 만약 인스턴스를 두 개 이상 사용해야 할 경우에는 두 개의 인스턴스에서 운영되는 두 개의 서버가 각각 scheduler에 할당된 API를 실행하기 때문에 1시에 예약을 했다면 1시에 두 번 실행이 되는 불상사가 일어나기 때문입니다. 물론 다른 회사들이나 서비스처럼 스케쥴링서버를 따로 운영해도 괜찮겠지만, 이 또한 스케쥴링을 담당하는 서버가 모종의 이유로 터져버리면… 주기적인 실행이 중단되어 버립니다. 이런 일들은 큰 오류이기 때문에 OS기반으로 운영되는 비교적 안전한 crontab을 사용하게 되었습니다.

설계

crontab을 사용해 주기적으로 실행할 스크립트를 작성해야 했습니다. API를 호출하기 위해 curl모듈을 사용하게 되었습니다. 그리고 shellscript 파일 또한 os에 종속시키기 보다 형상관리를 하면 좋을 것 같아 프로젝트 디렉토리의 /script폴더에 넣게 되었습니다. 그리고 API를 호출하기 위해서는 관리자 토큰이 필요합니다. 기한이 무제한인 토큰을 하나 발급받아 해당 인스턴스에 넣어두는 방법도 있지만, 보안적인 측면이나 토큰 알고리즘이 변경되었을 때 같은 유지보수를 위해 API호출 시 로그인을하고, 발급받은 토큰으로 바로 스케쥴링을 위한 API를 호출하는 것으로 하게 되었습니다. 이때 관리자 ID, PW, 호출할 URL은 .env파일에 넣어두고 해당 .env파일에서 변수 값을 가져와서 사용했습니다.

사용방법

url

사용방법이 굉장히 간단한 편입니다. 다음과 같은 규칙으로 운영되고, 기본은 분, 시, 일, 월, 요일 단위로 구분하여 스케쥴링이 가능합니다. 위 사진은 cron의 사용방법이고, cron을 이용해 스케쥴링을 도와주는 crontab의 사용방법에 대해 알아보겠습니다.

# 적용중인 스케쥴러 목록 확인하기
> crontab -l

# 스케쥴러 수동으로 등록, 변경하기
# 스케쥴러 수정창으로 들어가시면, 기본적으로 nano 편집기가 적용되어 있습니다.
> crontab -e

# 스케쥴러 목록 모두 삭제하기
> crontab -r

저는 이 세개로도 충분히 crontab을 사용할 수 있었습니다! 다양한 옵션이 있으니 찾아보시면 될 것 같습니다!

적용

calculate.sh

#!/bin/bash

# .env에 있는 변수 모두 지역적으로 등록
set -o allexport
source /home/{project위치}/.env
set +o allexport

# 관리자 로그인
token=$(curl --location -s --request POST "$SCHEDULER_URL/api/v1/admins/login" \
--header 'Content-Type: application/json' \
--data-raw '{
  "email": "'$ADMIN_ID'",
  "password": "'${ADMIN_PASSWORD}'"
}' | jq '.data.token')

# 인증 랭킹
curl --location -s -o /dev/null --request POST "$SCHEDULER_URL/api/v1/certification-rankings/hour" \
--header "Authorization: ${token:1:153}" \
--data-raw ''

다음과 같은 스크립트파일을 만들고 주기적으로 실행하겠습니다! 사실 이 스크립트에도 많은 도전과 역경이 있었습니다… .env파일의 변수를 불러오지 못한다던가, 문자열 객체안에 변수를 집어넣는 법을 모른다던가, API호출 후 결과 JSON에서 토큰을 꺼내오지 못한다던가… 하는 문제들이 있었지만 여러 가지를 찾아보면서 알아낼 수 있었습니다.

crontab

# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h  dom mon dow   command

SHELL=/bin/bash # 기본 실행하는 쉘의 종류

# 1시간마다
0 * * * * /home/{프로젝트 위치}/scripts/calculateRank.sh

# 매일 정각
0 15 * * * /home/{프로젝트 위치}/scripts/giveUserHeart.sh

# 매월 1일 정각
0 15 28-31 * * [ $(date +\%d -d tomorrow) -eq 1 ] && /home/{프로젝트 위치}/scripts/resetHeartCount.sh

처음 crontab -e명령어를 사용하면 위의 주석이 반겨줍니다! 그 밑에 자신이 사용할 스케쥴러를 등록해줍니다. 저는 한시간, 매일정각, 매월 1일을 기준으로 작성했습니다! liunx시간은 본초자오선 기준이라 우리가 원하는 시간에서 시차인 9시간을 빼줘야 한국시간으로 정확하게 돌아갑니다! 만약 본인의 linux시간을 한국시간으로 변경하신분은 한국시간 기준으로 작성해주시면 됩니다!

다음과 같은 설정을 모두 마치시면 설정한 시간에 맞춰 스케쥴러가 작동이 됩니다! 이제 로그를 찍어보며 잘 잘동이 되는지 확인하면 됩니다.

마무리

이렇게 crontab을 이용한 스케쥴링으로 API를 원하는 주기에 맞춰 실행할 수 있었습니다. 개인적으로 Shell Script에 대한 지식이나 이해가 부족해 생각보다 시간이 오래걸렸던 것 같습니다. 그래도 이번에 linux에 대한 이해나 shell script, curl, cron에 대해서 더 알아갈 수 있었던 유용한 시간이었습니다.

참고자료

업데이트:

댓글남기기