서버관리_14 메모리 스왑 감시하기

 
  • 출처 : 유닉스 리눅스 쉘스크립트 예제사전_한빛미디어

명령어: df, awk, read, echo, rm
키워드: 메모리, 감시, 스왑
사용처: 남은 메모리를 정기적으로 감시해서 스왑이 발생하면 경고하고 싶을 때

실행 예제

$ ./swapcheck.sh
[2023/09/08 15:15:15] Swap Alert: 352 (si+so)
ALERT...

스크립트

#!/bin/sh

# 감시할 스왑 발생 횟수. 이 숫자를 넘기면 경고
swapcount_limit=10 # ------------------------------------------------------- 1

# vmstat 명령어 출력에서 스왑인, 스왑아웃 값 취득
swapcount=$(vmstat 1 6 | awk 'NR >=4 {sum += $7 + $8} END{print sum}') # --- 2

# 스왑 횟수가 허용값을 넘기면 경고
if [ "$swapcount" -ge "$swapcount_limit" ]; then # ------------------------- 3
  # 현재 시각을 [2023/09/08 15:15:15] 형태로 조합
  date_str=$(date +'%Y/%m/%d %H:%M:%S') # ---------------------------------- 4

  # 스왑 발생 경고 출력
  echo "[$date_str] Swap Alert: $swapcount (si+so)" # ---------------------- 5
  /home/user1/bin/alert.sh
fi

해설

이 스크립트는 현재 서버 메모리 상태를 확인해서 메모리 부족이 일어나지 않는지 감시합니다. 여기서 메모리 부족은 서버에서 발생하는 스왑인, 스왑아웃 횟수로 판별합니다. 빈번히 스왑이 발생하면 메모리가 부족하다고 판별하고, 경고 메시지를 표시합니다.

스왑 횟수는 vmstat 명령어로 취득하고, 셸 별수 swapcount_limit로 지정한 값보다 최근 5초간 스왑인, 스왑아웃 횟수가 크면 alert.sh 스크립트를 실행합니다. 그리고 예제에서 alert.sh는 통지 메일을 송신하는 등으로 경고를 보내는 스크립트라고 가정합니다.

1에서 스왑 횟수 감시 허용값을 설정합니다. 이 스크립트는 1초마다 5번 계측해서 스왑인, 스왑아웃 횟수를 모두 더한 값이 허용값 이상이면 경고합니다. 여기서 스왑 횟수 허용값 10이란 ‘가끔 경고가 나오는 것은 괜찮아도 계속 이어지면 문제가 발생했다고 보는 값’이라고 합시다. 환경에 따라서 실제 허용값으로 변경하기 바랍니다. 일반적으로 아파치 httpd 같은 웹 서버에서 정적 컨텐츠를 반환하기만 한다면 디스크에 있는 컨텐츠를 리퀘스트에 따라 보낼 뿐이므로 그다지 메모리가 들지 않습니다. 웹 서버나 자바 애플리케이션 등을 실행하는 애플리케이션 서버는 많은 메모리를 사용하므로 스왑 발생에 주의해야 합니다.

2에서 스왑 횟수를 취득하기 위해 vmstat 명령어를 실행하빈다. vmstat 명령어는 서버의 현재 리소스 상태를 표시합니다. OS에 다라 표시 형식이 다르므로 여기에서는 리눅스 예를 소개합니다. FreeBSD나 Mac은 나중에 설명합니다.

  • vmstat 명령어 실행 예(리눅스)
    $ vmstat 1 3
    procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
     r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
     3  0	160480	116856	    0	308320	  0	   1	  25	   4	 41	  74	0	 0	99	0	 0
     0  0	160480	116856	    0	308352	  0	   0	   0	   0	118	 250	5	 0	95	0	 0
     0  0	160480	116856	    0	308352	  0	   0	   0	   0	148	 322	8	 1	91	0	 0
    

vmstat 명령어 인수로 1 3을 지정합니다. 첫 인수가 몇 촘다 계측할 것인가를 지정합니다. 두 번째 인수가 몇 번 계측할 것인가를 정하는데 여기서는 1초마다 3회 측정합니다. vmstat 명령어로 다양한 데이터를 얻을 수 있지만 여기서는 —swap— 열에만 주목합니다. si가 스왑인, so가 스왑아웃 횟수입니다. 따라서 7번째 컬럼과 8번째 컬럼 숫자를 더한 값이 지표입니다.

vmstat 명령어 첫 줄은 현재 상태가 아니라 서버 기동 시부터 평균값을 출력합니다. 따라서 이 값은 현재 상태와 다른 값일 때가 많습니다. 따라서 감시 용도로 vmstat명령어 첫 번째 출력값은 무시하는 것이 좋습니다.

2에서 awk 명령어로 NR >= 4로 필터해서 헤더 두 줄과 첫 번째 출력값을 넘기고 4번째 줄부터 데이터를 취득합니다. 그리고 스왑 횟수 si와 so는 7번째 컬럼과 8번째 컬럼에 있으므로 $7과 $8 값을 sum이란 awk 변수에 더합니다. 마지막으로 END 블록으로 sum을 출력하면 최근 5초간 스왑 횟수를 표시할 수 있습니다. 이 스왑 횟수는 명령어 치환 $()을 이용해서 셸 변수 swapcount에 대입합니다.

3에서 계측한 스왑 횟수가 미리 정의한 허용값을 넘었는지 if문으로 판별해서 분기합니다. test 명령어의 ‘이상’을 의미하는 -ge 연산자로 셸 변수 swapcount(스왑 횟수)와 셸 변수 swapcount_limit(허용값)을 비교합니다.

스왑 횟수가 허용값보다 크면 우선 4에서 date 명령어를 사용해서 현재 시각을 2023/09/08 15:15:15 같은 형태로 조합합니다. 감시 스크립트에서는 문제 발생 시각을 확인할 수 있게 시간을 함께 표시하는게 중요합니다.

마지막으로 5에서 경고 표시를 하고 스왑 발생 횟수를 출력합니다. 이런 스크립트는 서버 메모리 상태를 감시하기 위해 cron에 등록해서 정기적으로 실행하면 좋습니다.

FreeBSD나 Mac의 경우

FreeBSD의 vmstat 명령어는 리눅스와 표시 형식이 다릅니다.

  • FreeBSD vmstat 실행 예
    % vmstat 1 3
    proc	memory			page			disks			faults			cpu
    r b w	avm	fre	flt	re	pi	po	fr	sr	ad0	cd0	in	sy	cs	us	sy	id
    1 0 0	490M	420M	686	1	1	0	718	819	0	0	20	253	236	1	3	97
    0 0 0	390M	420M	1	0	1	0	0	0	1	0	3	127	137	0	0	100
    0 0 0 490M	420M	0	0	0	0	0	0	0	0	3	117	119	0	0	100
    

FreeBSD는 si/so가 없고 pi(페이지 인)/po(페이지 아웃)으로 스왑 발생 횟수를 취득할 수 있습니다. 여기서는 8, 9번째 컬럼이므로 [2]{:.info}는 다음처럼 수정합니다.

swapcount=$(vmstat 1 6 | awk 'NR >=4 {sum += $8 + $9} END{print sum}')

Mac에서는 vmstat 명령어가 없는 대신 vm_stat 명령어가 있습니다. 사용 방법과 출력 방법도 리눅스와 상당히 다릅니다.

% vm_stat -c 3 1
Mach Virtual MemoryStatistics: (page size of 4096 bytes)
free	active	specul	inactive	throttle	wired		prgable	gaults	copy	0fill	reactive	purged	file-backed	anonymous	cmprssed	cmprssor	dcomprs	comprs	pageins		pageout	swapins	swapouts
4084	1572367	5307	1652012			0	777742		33468	464576K	9069783	290309K	2467769		1358643	1569998		1668688		943514		182192		477033	195147	43568086	596465	59042	351103
3608	1571444	5321	1652016			0	778499		33118	568	0	214	0		0	1561029		1667752		943514		182192		0	0	0		0	0	0
4420	1573189	4565	1652019			0	776887		33926	3031	3	642	0		2	1560286		1669487		943514		182192		0	0	0		0	0	0

Mac의 vm_stat 명령어는 계측 횟수를 -c옵션으로 지정하고 인터벌은 명령어 첫 번째 인수로 지정합니다. 그리고 -c 옵션은 최신 버전에 생겼으므로 예전 버전에서는 사용할 수 없습니다.

Mac의 vm_stat 명령어는 FreeBSD처럼 페이지 인(pageins)과 페이지 아웃(pageout) 횟수를 취득하면 스왑 발생 횟수를 알 수 있습니다. 단, vm_stat 명령어는 출력 형식도 버전에 따라 다른데 10.9(Mavericks)부터 컬럼 구성이 크게 변했습니다. 따라서 vm_stat 명령어를 직접 실행해보고 pageins와 pageout 위치를 찾아서 2를 수정하기 바랍니다.

주의사항

  • 이런 메모리 감시를 셸 스크립트로 하는 방식은 소규모 환경에서 보조적인 용도롤 사용하는 경우가 많습니다. 대규모 감시 시스템 구성은 자빅스(Zabbix)나 나기오스(Nagios) 사용을 검토해보기 바랍니다.

  • 자바 애플리케이션을 실행한다면 메모리 감시에는 스왑뿐만 아니라 가비지 컬렉션(특히 Full GC) 빈도도 중요해집니다. 자바 전문서를 참조해보기 바랍니다.