필요성
메모리 누수(Memory Leak)가 있는 서비스가 있을 수도 있다. 이런 서비스를 체크해 재시작하거나 알림/로깅 등을 하고 싶을 수 있는데, 이런 상황을 가정해 “메모리 사용량이 80%에 도달하면 서비스를 재시작”하는 스크립트 작성법을 정리해봤다.
물론 현업에서는 그래프 형태로 메모리 사용량 등을 트래킹 할 수 있어야 할 것이고, 모니터링 과정에서 이상이 발견되면 알림이나 경고가 올 수 있어야 할 것이다.
하지만 경우에 따라서는 shell script를 짜서 메모리 사용량을 체크해야할 수도 있으므로 한번 정리해 보려고 한다.
구현
메모리 사용량은 free
라는 명령어로 체크하는데,
먼저 free 명령어를 간단히 살펴보자.
% free
total used free shared buff/cache available
Mem: 26158768 520580 25362464 68 275724 25298544
Swap: 7340032 0 7340032
메모리 사용량과 총량 등을 확인할 수 있다.
여기서 보고싶은 것은 스왑 영역이라기 보다는 메모리이므로 grep
을 통해 memory만 가져와 사용량을 체크하려고 한다.
free | grep Mem
free
명령어의 결과에서 Mem
라인만 가져오게 된다.
다음으로, 우린 사용량 / 전체용량 * 100
이라는 식을 통해 메모리 사용량을 계산하고 싶다.
계산을 편리하게 하기 위해 MEMTOTAL
, MEMUSED
라는 변수 2개를 선언해보자.
awk
라는 명령어를 사용할 것인데, awk
사용법은 여기를 참고하자.
MEMTOTAL=`free | grep Mem | awk {'print $2'}` # Mem 에서 total만 가져옴
MEMUSED=`free | grep Mem | awk {'print $3'}` # Mem에서 used만 가져옴
free | grep Mem
의 결과는 아래와 같고, 우리는 2번째 인수인 26158768
(total)과 세번째 인수인 519512
(used)를 가져오고 싶다.
print
는 출력을 의미하고, $2
는 2번째 인수, $3
은 3번째 인수를 의미한다.
% free | grep Mem # Mem 라인만 가져온 결과
Mem: 26158768 519512 25363048 68 276208 25299604
이제 본격적으로
shell script를 작성하자.
#!/bin/bash
# 서버의 총 메모리 사용량이 80% 이상일 경우 서비스 재기동
MEMTOTAL=`free | grep Mem | awk {'print $2'}`
MEMUSED=`free | grep Mem | awk {'print $3'}`
usage=`echo ${MEMUSED}*100/${MEMTOTAL} | bc`
# usage가 80%를 넘으면 서비스 재시작
if [ $usage \> 80 ];
then
systemctl restart MyAwesomeService
else
exit 0
fi;
systemctl restart [서비스명]
명령어로 조건에 맞을 경우 재시작하도록 스크립트를 작성했다.
작은 문제가 하나 있다. 위의 usage
를 계산하는 연산식은 나눗셈 결과에서 소숫점은 버림한다.
예를들면 79.9는 79가 된다. 소숫점 첫째 자리에서 반올림을 하는 것이 여러모로 보나 자연스러울 것 같다.
소숫점 자리에서 반올림을 하게 수정해봤다.
조금 복잡해졌는데, 함수를 만들어 사용했다.
함수 내부의 반올림 연산식은 일종의 수학적 트릭이다. 자세히 알고싶다면 여기를 참고하자.
대충 $(( (($1 * 100) + ($2 / 2)) / $2 ))
이 연산은 첫번째 인수를 두번째 인수로 나눠 반올림한 후 100을 곱해 %로 환산하는 식이라고 이해하면 된다.
#!/bin/bash
# 서버의 총 메모리 사용량이 80% 이상일 경우 서비스 재기동
MEMTOTAL=`free | grep Mem | awk {'print $2'}`
MEMUSED=`free | grep Mem | awk {'print $3'}`
# 반올림 함수
round() {
rounded=$(( (($1 * 100) + ($2 / 2)) / $2 ))
echo $rounded
}
usage=$(round $MEMUSED $MEMTOTAL)
if [ $usage \> 80 ];
then
exit 0
else
echo $usage
fi;
결론
반올림까지 구현은 해봤지만, 현업에서 실제 사용한다면 좀 더 간단한 버전을 쓸 것 같다.
- 간단한 버전이 제3자가 이해하기 쉽다.
- 79.9%를 79%라고 한들 메모리 관리 측면에서 큰 문제가 생길 것 같지는 않다.
더불어 crontab을 이용해 주기적으로 메모리 사용 상황을 체크하게 하고, 80% 이상 사용시 서비스를 재시작 하는 방식으로 조합해 사용할 수 있을 것 같다.
참고자료
https://recipes4dev.tistory.com/171
https://codechacha.com/ko/shell-script-ceiling-halfup-floor/