본문 바로가기
이것저것구축하기/Linux관련

SFTP이용하여 전송 후 프로세스 재시작

by 곰네Zip 2022. 8. 29.

배포를 하려다보니 일일이 서버에 FTP접속해서 올리고, 서버에서 프로세스 찾아서 내리고 다시 실행하고.. 귀찮다.

리눅스 쓰면 스크립트 뒀다 뭐하나 ㅋ

우선 할일을 정리해보면..

1. SFTP로 접속하여 파일을 올린다. (실행중인데 덮어씌울 순 없으므로 임시 디렉토리에..)

2. 실행중인 프로세스를 찾아서 죽인다.

3. 업로드한 파일을 실행하려는 파일이 있는 위치로 복사후 실행

4. SSH로 접속하여 서버의 스크립트 실행 (서버에서 실행하는 스크립트를 별도로 만드는건.. 로컬에서 서버에 무슨 변화가 있던지간에.. 그냥 서버한테 스크립트 실행해달라고 던지기만 하게.. 안그러면 서버에 소소한 변화도 로컬에서 다 컨트롤해야하니까 귀찮아진다..)

 

여기서 2,3 항목은 서버에서 실행 가능하다.

SFTP에서도 뭔가 방법이 있을까.. 했더니 서버에서 실행 가능한 방법은 없는것 같더라.

그러면 script를 이용해서 ssh접속 시, 실행 가능한 커맨드들을 모아서 실행하도록 만들 수 있으니까. 그걸 사용하면 어떻게든 되지 않을까???

 결론은 성공.

 

우선 SFTP접속하여 파일 업로드하는 부분은 이렇게..

#!/bin/bash
REMOTE_FTP_ADDR="서버주소"
REMOTE_USER="계정"
AUTHFILE="pem파일경로"
DATE=$(date +%y%m%d)
LOCAL_DIR="업로드할BinaryFile경로"
SERVER_DIR_BASE="./bins"
FILE_NAME="MyApp.jar"

if [ ! -z ${1} ]
then
	FILE_NAME=${1}
fi

sftp -i $AUTHFILE $REMOTE_USER@$REMOTE_FTP_ADDR  << EOF
cd $SERVER_DIR_BASE
mkdir $DATE
cd $DATE
lcd $LOCAL_DIR
put $FILE_NAME
quit
EOF

바이너리 업로드할 폴더는 백업(?)폴더에 올리기 위해 날짜 기준으로 서버에 임시 경로를 만들기 위해. 저 경로를 받아놓는거..

여기서는 FILE_NAME만 스크립트의 파라미터로 받는데, 경로들도 파라미터로 받아와도 되고, 아니면 파라미터로 받지 말고 고정으로 놓고 사용해도 괜찮다.

중요한건.. sftp -i pem파일 계정@주소 << EOF로 접속하는거.

접속한 이후에는 cd $SERVER_DIR_BASE부터 quit까지는 sftp접속 후, 실행할 명령어들이다.

파일 만들고 업로드. 그리고 끝!

여기서 EOF를 주어, 이번 실행은 여기까지.. 나머지는 sftp에 접속해서 수행하라고 알려준다.

여기까지가 1번 과정 파일 업로드 하는 script

 

2. 실행중인 프로세스 찾아서 죽이기.

ps -elf | grep MyApp.jar | grep java | awk '{print $4}'

위 스크립트는 실행중인 프로세스 중 내가 찾는 프로세스의 PID를 가져오기 위함이다.

ps -elf로 전체 목록을 얻어오는데, 그 중 내가 원하는 프로세스의 PID를 찾기위해 내 App의 이름을 검색해야지.

근데 이걸 하면 'ps -elf | grep MyApp.jar'를 같이 검색해서 보여준다. 즉, 실행중인 명령어 + 찾는 명령어 두개가 뜬다.

MyApp.jar는 java -jar MyApp.jar로 실행했으므로, 실행중인 명령어에는 java라는 단어가 들어가게된다. 그러니 그 목록 중에서 다시 java를 포함한 항목을 잡아내라고 grep java를 파이프로 연결.

마지막으로 PID만 추출하기 위해, awk '{print $4}'를 연결해준다. PID는 4번째 항목에 표시되므로, awk를 이용해 레코드처럼 표시되게 해주고. 그 중 4번째것만 출력해달라고 저 옵션을 붙인다. (만약 3번째 항목을 보고싶으면 $4를 $3으로..)

 

3. process죽이기

 process ID를 알면 kill $PROC_ID를 이용해서 죽이면 된다. 자동화를 하기 위하여 이 스크립트를 짜는거니까.

당연히 2번의 스크립트를 수정하자.

PROC_ID라는 변수에 실행 결과값을 얻기 위해서는 아래와 같이 작성하자

PROC_ID=$(command param)

 그리고 파일을 복사하는 명령어는 cp source dest이다.

이것도 스크립트로 쓰면

#!/bin/bash
FILE_NAME="MyApp.jar"
PRODUCT_PATH="./MyApps"
UPLOAD_PATH="./bins/220829"

cp $UPLOAD_PATH/$FILE_NAME $PRODUCT_PATH/$FILE_NAME

 백업된 파일 경로는 자주 바뀔테니까 변수로 처리하자.

 Process죽이고, 파일교체하는 작업 다음에는 프로세스를 실행하면 된다.

근데 나는 백그라운드로 실행하고자 한다. (Terminal이 종료되어도 실행되게)

nohup java -jar -Dspring.profiles.active=프로파일명 실행할경로/실행할jar파일이름 &

프로파일은 없는경우 제외해도 되고.. nohup으로 실행하고 마지막에 &는 붙여줘야한다. 그래야 백그라운드로 실행되고, 터미널이 종료되어도 프로세스는 혼자 돈다.

 

위 내용을 다 합치면 아래와 같이 최종적으로 나오게 된다.

#!/bin/bash
FILE_NAME="MyApp.jar"
PRODUCT_PATH="./MyApps"
UPLOAD_PATH="./bins/220829"

if [ ! -z ${1} ] 
then
	FILE_NAME=${1}
fi

if [ ! -z ${2} ]
then 	
	UPLOAD_PATH=${2}
fi
PROC_ID=$(ps -elf | grep $FILE_NAME | grep java | awk '{print $4}' )
kill $PROC_ID
cp $UPLOAD_PATH/$FILE_NAME $PRODUCT_PATH/$FILE_NAME
nohup java -jar -Dspring.profiles.active=내프로파일 $PRODUCT_PATH/$FILE_NAME &

 이렇게 하면 스크립트를 실행할 때, 업로드된 파일 경로와 파일 이름을 파라미터로 받아서, 실행중인 프로세스를 죽이고, 파일을 교체하고, 실행하는 스크립트까지 작성된거다.

 

4. ssh로 접속하여 서버의 스크립트 실행하기

 서버에서는 준비가 다 되었다. 그러면, sftp로 업로드가 끝나면, 로컬에서 ssh접속해서 스크립트를 실행해야지.

ssh -i pem파일 -l 계정 서버주소 실행할commands

위와 같이 작성하면 된다.

그러면 로컬의 최종 스크립트는..

#!/bin/bash
REMOTE_FTP_ADDR="서버주소"
REMOTE_USER="계정"
AUTHFILE="pem파일경로"
DATE=$(date +%y%m%d)
LOCAL_DIR="업로드할BinaryFile경로"
SERVER_DIR_BASE="./bins"
FILE_NAME="MyApp.jar"

if [ ! -z ${1} ]
then
	FILE_NAME=${1}
fi

sftp -i $AUTHFILE $REMOTE_USER@$REMOTE_FTP_ADDR  << EOF
cd $SERVER_DIR_BASE
mkdir $DATE
cd $DATE
lcd $LOCAL_DIR
put $FILE_NAME
quit
EOF
RUN_SCRIPT="./myapp_run.sh $FILE_NAME $SERVER_DIR_BASE/$DATE"
ssh -i $AUTHFILE -l $REMOTE_USER $REMOTE_FTP_ADDR $RUN_SCRIPT

이렇게 만들 수 있다.

 

반응형

댓글