이번 주차는 저번 주차와 똑같이 서비스 로직만 작성하게 되었다.
토요일, 일요일부터 도커를 적용하기 위해 씨름하고 있는데 어려운 것 같다.
그 와중에 우리 조는 Git Action, CodeDeploy 를 통해 CI-CD 파이프 라인을 구축해놓았다.
허나, 코드 디플로이에서 배포가 완료된 후 jar 파일을 nohup 으로 실행시켜주는 쉘 스크립트가 정상적으로 작동되지 않는 상황이 발생했다,,,
발생이라고 하는 것보단 원래 안 됐었는데, 그냥 방치해두다가 내가 고쳤다..ㅋㅋ
우리 프로젝트의 배포 스크립트는 2개가 존재했다. stop, start.sh 로 말이다.
stop.sh 코드
#!/usr/bin/env bash
PROJECT_ROOT="/home/ubuntu/BulletBox"
JAR_FILE="$PROJETC_ROOT/bulletBox-webapp.jar"
DEPLOY_LOG="$PROJECT_ROOT/deploy.log"
TIME_NOW=$(date +%c)
# 현재 구동 중인 애플리케이션 pid 확인
CURRENT_PID=$(pgrep -f $JAR_FILE)
# 프로세스가 켜져 있으면 종료
if [ -z $CURRENT_PID ]; then
echo "$TIME_NOW > 현재 실행중인 애플리케이션이 없습니다" >> $DEPLOY_LOG
else
echo "$TIME_NOW > 실행중인 $CURRENT_PID 애플리케이션 종료 " >> $DEPLOY_LOG
kill -15 $CURRENT_PID
sleep 5
fi
start.sh 코드
#!/usr/bin/env bash
PROJECT_ROOT="/home/ubuntu/BulletBox"
JAR_FILE="$PROJECT_ROOT/bulletBox-webapp.jar"
APP_LOG="$PROJECT_ROOT/application.log"
ERROR_LOG="$PROJECT_ROOT/error.log"
DEPLOY_LOG="$PROJECT_ROOT/deploy.log"
TIME_NOW=$(date +%c)
# 현재 구동중인 어플리케이션 PID 확인
CURRENT_PID=$(pgrep -f $JAR_FILE)
echo "$TIME_NOW > 실행된 프로세스 아이디 $CURRENT_PID 입니다." >> $DEPLOY_LOG
if [ -z $CURRENT_PID ]; then
echo "$TIME_NOW > 현재 실행중인 애플리케이션이 없습니다" >> $DEPLOY_LOG
else
echo "$TIME_NOW > 실행중인 $CURRENT_PID 애플리케이션 종료 " >> $DEPLOY_LOG
kill -15 $CURRENT_PID
sleep 5
fi
# build 파일 복사
echo "$TIME_NOW > $JAR_FILE 파일 복사" >> $DEPLOY_LOG
cp $PROJECT_ROOT/build/libs/*.jar $JAR_FILE
# jar 파일 실행
echo "$TIME_NOW > $JAR_NAME 파일 실행" >> $DEPLOY_LOG
nohup java -jar $JAR_FILE > $APP_LOG 2> $ERROR_LOG &
appSpec.yml
...
hooks:
AfterInstall: # AfterInstall: 기존에 실행중인 애플리케이션 종료
- location: scripts/stop.sh # location: hooks 에서 실행할 스크립트 위치
timeout: 60 # timeout (optional): 스크립트 실행에 허용되는 최대 시간이며, 넘으면 배포 실패로 간주됨
runas: ubuntu # runas (optional): 스크립트를 실행하는 사용자
ApplicationStart: # ApplicationStart: 새로운 애플리케이션 실행
- location: scripts/start.sh
timeout: 60
runas: ubuntu
stop.sh 코드는 우리 프로젝트 jar 파일이 실행중이면, 종료해주는 스크립트였다. (hooks 으로 stop.sh 을 먼저 띄워서 if 분기 태움)
start.sh 코드는 stop.sh 이 실행되고, 그 다음에 실행되도록 되어있었다.
먼저, 코드를 읽어보니, 스크립트가 두 개 존재할 필요가 없다고 생각되었다.
두 스크립트의 차이는 jar 파일이 실행되어 있으면 PID 확인 후 kill 쳐주는 것이다. 하지만, 이는 하나의 스크립트에서 작성해도 무방하다.
그래서 start.sh 로 다 합쳐주었다.
또한 appSpec.yml에서 hooks의 ApplicationStart도 지웠다.(스크립트가 하나라 필요가 없음)
start.sh
#!/usr/bin/env bash
PROJECT_ROOT="/home/ubuntu/BulletBox"
JAR_FILE="$PROJECT_ROOT/bulletBox-webapp.jar"
APP_LOG="$PROJECT_ROOT/application.log"
ERROR_LOG="$PROJECT_ROOT/error.log"
DEPLOY_LOG="$PROJECT_ROOT/deploy.log"
TIME_NOW=$(date +%c)
# 현재 구동중인 어플리케이션 PID 확인
CURRENT_PID=$(pgrep -f $JAR_FILE)
echo "$TIME_NOW > 실행된 프로세스 아이디 $CURRENT_PID 입니다." >> $DEPLOY_LOG
if [ -z $CURRENT_PID ]; then
echo "$TIME_NOW > 현재 실행중인 애플리케이션이 없습니다" >> $DEPLOY_LOG
else
echo "$TIME_NOW > 실행중인 $CURRENT_PID 애플리케이션 종료 " >> $DEPLOY_LOG
kill -15 $CURRENT_PID
sleep 5
fi
# build 파일 복사
echo "$TIME_NOW > $JAR_FILE 파일 복사" >> $DEPLOY_LOG
cp $PROJECT_ROOT/build/libs/*.jar $JAR_FILE
# jar 파일 실행
echo "$TIME_NOW > $JAR_FILE 파일 실행" >> $DEPLOY_LOG
nohup java -jar $JAR_FILE > $APP_LOG 2> $ERROR_LOG &
appSpec.yml
...
hooks:
AfterInstall: # AfterInstall: 기존에 실행중인 애플리케이션 종료
- location: scripts/start.sh # location: hooks 에서 실행할 스크립트 위치
timeout: 60 # timeout (optional): 스크립트 실행에 허용되는 최대 시간이며, 넘으면 배포 실패로 간주됨
runas: ubuntu # runas (optional): 스크립트를 실행하는 사용자
사실 비교해보면, 코드가 완전히 바뀐 것은 아니다. 근데 하나로 합쳐줬더니 잘 실행이 되는,,?
자세히는 잘 모르겠지만, 짐작 가는 부분은 있긴 하다.
바로, hooks 이벤트 생명주기인 것 같다.
hook의 EC2/온프레미스 배포 후크를 확인해보면, AfterInstall -> ApplicationStart 로 수명 주기가 이어진다.(전후과정 생략) 근데, 변경 전에 AfterInstall 이벤트를 통해 PID를 kill친 후, ApplicaionStart 이벤트로 새로운 jar 파일을 실행시켜주는 것이다.
근데,,, 왜 이벤트가 발생하지 않았던 건지는 잘 모르겠다.. 그래서 변경 후를 확인해보면, AfterInstall 이벤트(프로젝트 구성 시 스크립트 실행)는 ApplicationStart 이벤트를 대신해서 사용할 수 있다. 그래서 하나의 start.sh을 AfterInstall 이벤트를 통해 읽도록 구성하였다.
그래도 어찌저찌 잘 된 것 같아 뿌듯하긴 하지만, 이유를 알 수 없어 찜찜..