쉘 스크립트와 crontab을 활용한 배포 자동화

kakasoo·2021년 3월 7일
4

나는 aws에서 프리티어로 제공된 ubuntu 서버를 사용하고 있었다. 나중에 메모리 부족으로 인해서 -어떤 문제였는지는 다른 글에서 설명하도록 하고- 결국 라즈베리파이로 옮기긴 했으나, 기본적인 골자는 똑같기 때문에 aws 기준으로 설명을 한다.

문제 배경 1

  • local에서 작업을 한다.
  • github에 push를 한 직후, ssh 또는 putty로 aws에 들어간다. * 여기부터는 local이 아니다.
  • 이후 git fetch, git pull 등의 명령어로 새로운 코드 및 파일들을 가져온다.
  • 새로이 배포를 한다.
    • npm install
    • npm run build
    • pm2로 만든 서버라면 NODE_ENV=production pm2 restart 0
    • 나의 경우에는 nginx를 써서 배포했기 때문에 클라이언트는 build만 해두어도 됐다.

aws에서의 작업을 CMD 창에서 작성할 명령어로 표현하면 아래처럼 된다.

서버 측 명령어

# 서버의 경우
cd /home/폴더경로/server
git fetch
git pull
npm install
npm run build

# 서버를 실행시킨 적이 이전에 있었다면
NODE_ENV=production pm2 restart 0

# 서버를 새로 실행시키는 것이라면 restart 대신에 start 와 서버 빌드 경로를 작성한다.
NODE_ENV=production pm2 start ./dist/bin/www.js

클라이언트 명령어

# client의 경우
cd /home/폴더경로/client
git fetch
git pull
npm install
npm run build

# nginx에서 빌드된 파일 위치를 지정해놓았기 때문에 여기까지만 작업하면 된다.
# 이번 글은 nginx를 설명하는 것이 아니기 때문에 관련 내용은 생략한다.

매번 이러한 과정을 밟는 것은 상당한 시간이 걸린다. 그렇기 때문에 문제 배경에 나온 것을 자동화한다. 이는 쉘 스크립트라는 형태로 자동화를 할 건데, 이는 확장자가 .sh 이며 실행 시에는 ./fileName.sh의 형태로 작성하면 된다.

문제 해결

server.sh

# server 측 shell script
cd /home/ubuntu/github/server

git fetch

local=$(git rev-parse HEAD)
echo $local

target=$(git rev-parse origin/main)
echo $target

if [ $local != $target ]
then
        git stash
        git pull origin main
        echo '풀 완료'
        npm install
        npm run build
        pm2 stop 0
        NODE_ENV=production pm2 start ./dist/bin/www.js
fi

client.sh

cd /home/ubuntu/github/client

git fetch

local=$(git rev-parse HEAD)
echo $local

target=$(git rev-parse origin/main)
echo $target

if [ $local != $target ]
then
        git stash
        git pull origin main
        echo '풀 완료'
        npm install
        echo "npm install 완료"
        npm run build
        echo "빌드 완료"
fi

두 스크립트 모두 같은 구조로 되어 있는데, 일단 파일의 경로가 다를 경우가 있을 수 있으므로, 해당 파일의 위치로 가게 한다. 그 다음 git fetch로 origin에서 데이터를 가져온다. 다음에는 local과 origin에서의 HEAD를 비교하여, 만약 이것이 다를 경우에는 아래의 명령어들을 실행한다.
여기서부터는 서버와 클라이언트가 배포되는 방식에 따라 코드가 달라질 수 있는데, 기본적으로는 혹여 서버나 클라이언트에서 직접 작업한 내용이 있을 수 있으므로 git stash로 모두 날려준다. 이는 git pull을 할 때 충돌이 나는 것을 방지한다. 다음은 새로운 모듈이 추가됐을 경우를 대비하여 npm install을 한 상태에서 build 명령을 한다.
서버의 경우에는 pm2 명령어를 추가로 작성해주었다. 중간 중간에 나오는 echo는 console 창에 문자열을 띄우는 명령어이다.

앞서 말했듯이 해당 폴더 경로에서 ./server.sh 또는 ./client.sh 라고 입력하면 저 명령어들을 순차적으로 실행하게 된다. 따라서 여러 번 타자를 칠 필요 없이 하나의 명령어로 실행될 수 있도록 단축할 수 있다.

문제 배경 2

  • 쉘 스크립트로 자동화를 했지만, 결국 ssh나 putty를 써서 aws에 들어온 다음, 쉘 스크립트 실행 명령어를 입력해주어야 하는 상황은 그대로이다.
  • 따라서 aws에서 쉘 스크립트를 정해진 시간마다 실행시키도록 한다.

문제 해결 2

이는 사실 쉘 스크립트를 사용하고 난 다음이라면 무척이나 간단하다. 나는 ubuntu에 기본적으로 같이 있을, crontab을 사용하였다. crontab은 crontab -e 라고 작성하면 바로 에디터가 나오기 때문에 여기서 작성하면 된다. crontab을 처음 쓰면 작성 후에 해당 파일 위치가 어딘지 몰라 당황할 수 있는데, 걱정할 필요는 없다. crontab에서 작성한 것은 ubuntu의 계정에 종속되는 것이기 때문에, 다시 crontab -e를 작성하여 들어갈 수도 있다. 다른 옵션들도 참고하면 좋을 듯 하다. 일단 해당 코드를 아래에 게시한다.

crontab

SHELL=/bin/bash
PATH=${PATH} # 이 부분에 대해서는 아래의 텍스트를 참고!

* * * * * /home/ubuntu/github/client/client.sh
* * * * * /home/ubuntu/github/server/server.sh

위의 별 기호들이 의미하는 것은 시간을 의미한다. 나의 경우에는 1분마다로 설정하였는데, 개발이 얼추 끝난 직후에는 굳이 1분마다 할 필요가 없다. 시간 간격으로 설정할 필요없이, 특정 시간 ( 사용자가 없을 밤 시간 대 )로 배포하게끔 하면 될 것이다.
PATH 라고 작성된 부분은 위 내용을 그대로 작성해서는 안 된다. echo ${PATH} 라고 작성하여 경로를 알아낸 다음에, 그 경로를 복사하여 넣어주자. 상당히 긴 텍스트가 나올 것이다.

결론

  • 쉘 스크립트와 crontab의 기본적인 내용만 알고 있어도, 개발이 무척이나 편해진다.
  • 초기에 설정을 해두면 이후 작업이 무척이나 편해지므로, 환경 설정 및 세팅에 시간을 아끼지 말자.
profile
자바스크립트를 좋아하는 "백엔드" 개발자

0개의 댓글