리눅스 free 명령어 사용법 - available과 buff/cache 제대로 읽기
이 명령어를 언제 쓰는가
애플리케이션이 OOM Killer에게 죽었다는 보고를 받았을 때, 정말 메모리가 부족한 상황인지 판단하는 첫 명령이다.
free를 제대로 읽지 못해서 벌어지는 일이 의외로 많다. "free가 300MB밖에 없다"며 캐시를 강제로 비우거나, 스왑을 쓰고 있다는 이유만으로 서버를 늘리는 식이다. 리눅스 메모리 관리에서 남는 메모리는 낭비라는 원칙을 이해하면 이런 판단 착오를 피할 수 있다.
기본 형식
free [-h|-m|-g] [-w] [-s 초 -c 횟수]
free는 /proc/meminfo를 읽어서 보기 좋게 정리해 주는 도구다. 그래서 free의 모든 값은 /proc/meminfo에서 직접 확인할 수 있다.
자주 쓰는 옵션
| 옵션 | 의미 | 예시 |
|---|---|---|
| -h | 사람이 읽는 단위로 자동 변환 | free -h |
| -m / -g | MiB / GiB 단위로 고정. 스크립트 파싱에 좋다 | free -m |
| -w | buffers와 cache를 따로 표시 | free -wh |
| -s 초 | 지정 간격으로 반복 출력 | free -h -s 5 |
| -c 횟수 | 반복 횟수 지정(-s와 함께) | free -m -s 5 -c 12 |
| -t | 물리+스왑 합계 행 추가 | free -ht |
| -l | low/high 메모리 상세 | free -hl |
출력 읽는 법
total used free shared buff/cache available
Mem: 7.6Gi 2.1Gi 318Mi 196Mi 5.2Gi 5.1Gi
Swap: 2.0Gi 128Mi 1.9Gi
free는 아무 용도로도 쓰이지 않는 메모리다. 이 값이 작은 것은 문제가 아니라 정상이다. 리눅스는 쓰지 않는 물리 메모리를 전부 디스크 캐시(buff/cache)로 돌려서 파일 읽기를 빠르게 한다. 애플리케이션이 메모리를 요구하면 커널이 캐시를 즉시 반납한다.
따라서 실제로 봐야 할 값은 맨 오른쪽 available이다. 이건 "지금 새 프로세스가 스왑을 건드리지 않고 쓸 수 있는 양"의 커널 추정치다. 위 예시는 7.6GiB 중 5.1GiB가 여유인 건강한 상태다. available이 total의 10% 아래로 떨어지면 그때가 진짜 경고 구간이다.
실전 예제
1) 현재 상태를 한 줄로 본다.
free -h
2) 메모리가 새는지 1분간 관찰한다. 배포 후 애플리케이션이 계속 메모리를 물고 늘어지는지 확인할 때 쓴다.
free -m -s 5 -c 12
3) 스왑을 실제로 쓰고 있는 프로세스를 찾는다. Swap used가 크다고 다 문제는 아니고, 어떤 프로세스가 스왑에 밀려났는지 봐야 판단이 선다.
sudo awk '/^VmSwap/ && $2+0 > 0 {print $2" kB", FILENAME}' /proc/*/status 2>/dev/null \
| sort -n | tail -5
4) OOM Killer가 실제로 돌았는지 확인한다. 애플리케이션이 이유 없이 사라졌다면 여기부터 본다.
sudo dmesg -T | grep -i 'killed process'
sudo journalctl -k --since '1 hour ago' | grep -i 'out of memory'
5) 임계치 알림용으로 available 비율을 계산한다. free 대신 available을 기준으로 삼는 것이 핵심이다.
free -m | awk '/^Mem:/ {printf "available %d MiB (%.1f%%)\n", $7, $7/$2*100}'
함정과 주의점
free 값이 작다고 메모리 부족이 아니다. 앞에서 설명한 대로 buff/cache는 언제든 회수되는 여유분이다. 모니터링 알림을 free 컬럼 기준으로 걸어 두면 정상 서버가 매일 경고를 울린다. available로 걸어야 한다.
캐시를 강제로 비우지 마라. echo 3 > /proc/sys/vm/drop_caches는 벤치마크를 같은 조건에서 재실행할 때 쓰는 도구지 운영용이 아니다. 실행하면 free 숫자는 예뻐지지만 이후 모든 파일 접근이 디스크로 가면서 I/O가 폭증하고 응답 시간이 나빠진다. 캐시가 다시 채워지면 free는 원래대로 돌아간다.
컨테이너 안에서 free는 호스트를 보여 준다. /proc/meminfo는 네임스페이스로 격리되지 않는다. 512MiB 제한이 걸린 컨테이너에서도 free는 호스트의 64GiB를 보여 주고, 그 말을 믿고 힙 크기를 잡으면 곧바로 OOM으로 죽는다. 컨테이너의 실제 한도는 cgroup에서 읽는다.
# cgroup v2
cat /sys/fs/cgroup/memory.max /sys/fs/cgroup/memory.current
# cgroup v1
cat /sys/fs/cgroup/memory/memory.limit_in_bytes
스왑이 남아 있어도 OOM은 난다. cgroup 메모리 제한에 걸린 경우, 커널이 연속된 물리 페이지를 확보하지 못한 경우, vm.overcommit_memory 설정에 따라 할당이 거부되는 경우 모두 스왑과 무관하게 죽는다. free만 보고 "스왑이 남았으니 메모리 문제는 아니다"라고 결론 내리면 안 된다.
구버전에는 available 컬럼이 없다. CentOS 6 시절의 procps(free 3.2.8)는 -/+ buffers/cache라는 별도 행으로 같은 정보를 표현했다. available 컬럼은 procps-ng 3.3.10 이후에 생겼다.
함께 보면 좋은 명령어
- top — 어느 프로세스가 메모리를 먹는지는 free가 알려주지 않는다.
M키로 정렬해서 본다. - vmstat —
vmstat 1의 si/so 컬럼으로 스왑 입출력이 지금 일어나고 있는지 확인한다. Swap used보다 이 값이 중요하다. - dmesg — OOM Killer가 무엇을 왜 죽였는지는 커널 로그에만 남는다.