free 명령어로 서버 장비의 메모리 사용량 체크하기

필요성

메모리 누수(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;

결론

반올림까지 구현은 해봤지만, 현업에서 실제 사용한다면 좀 더 간단한 버전을 쓸 것 같다.

  1. 간단한 버전이 제3자가 이해하기 쉽다.
  2. 79.9%를 79%라고 한들 메모리 관리 측면에서 큰 문제가 생길 것 같지는 않다.

더불어 crontab을 이용해 주기적으로 메모리 사용 상황을 체크하게 하고, 80% 이상 사용시 서비스를 재시작 하는 방식으로 조합해 사용할 수 있을 것 같다.

참고자료

https://recipes4dev.tistory.com/171

https://codechacha.com/ko/shell-script-ceiling-halfup-floor/

https://linuxize.com/post/free-command-in-linux/