리눅스 df 명령어 사용법 - 디스크 용량 확인과 inode 고갈 점검
이 명령어를 언제 쓰는가
"디스크 사용률 90%" 알림을 받았을 때 가장 먼저 치는 명령이다. 서버 전체가 아니라 마운트된 파일시스템별로 얼마나 남았는지 보여 주기 때문에, 루트가 찬 건지 로그 파티션만 찬 건지 데이터 볼륨이 찬 건지를 구분할 수 있다.
애플리케이션이 "No space left on device" 에러를 뱉는데 df에는 여유가 있어 보일 때도 df로 확인해야 한다. 이 경우 대개 용량이 아니라 inode가 고갈된 것이고, df -i로만 보인다.
기본 형식
df [옵션] [경로]
경로를 주면 그 경로가 속한 파일시스템 한 줄만 나온다. 경로가 어느 마운트에 속하는지 헷갈릴 때 유용하다. 경로를 생략하면 마운트된 전부를 보여 준다.
자주 쓰는 옵션
| 옵션 | 의미 | 예시 |
|---|---|---|
| -h | 사람이 읽는 단위(G, M)로 표시. 사실상 항상 붙인다 | df -h |
| -T | 파일시스템 타입(ext4, xfs, overlay) 표시 | df -hT |
| -i | 용량 대신 inode 사용량 표시 | df -i |
| -x 타입 | 해당 타입 제외. tmpfs 노이즈를 걷어낼 때 | df -h -x tmpfs |
| -t 타입 | 해당 타입만 | df -h -t ext4 |
| -P | POSIX 포맷. 한 항목이 반드시 한 줄로 나온다 | df -P /data |
| --total | 맨 아래에 합계 행 추가 | df -h --total |
| -a | 크기 0인 가상 파일시스템까지 전부 | df -a |
실전 예제
1) 노이즈를 걷어내고 실제 디스크만 본다. 요즘 배포판은 tmpfs 마운트가 열 개 넘게 잡혀서 그냥 df -h를 치면 정작 볼 게 안 보인다.
df -hT -x tmpfs -x devtmpfs -x squashfs
Filesystem Type Size Used Avail Use% Mounted on
/dev/vda1 ext4 49G 38G 8.6G 82% /
/dev/vdb1 xfs 197G 61G 137G 31% /data
2) 특정 디렉터리가 어느 파일시스템에 있는지 확인한다. DB 데이터 경로가 별도 볼륨인지 루트에 있는지 확인할 때 쓴다.
df -hT /var/lib/mysql
3) inode 고갈을 점검한다. 세션 파일이나 캐시 파일이 수백만 개 쌓이면 용량은 남아도 파일을 못 만든다. IUse%가 100%면 이게 원인이다.
df -i -x tmpfs
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/vda1 3211264 3211264 0 100% /
4) 임계치를 넘은 파일시스템만 골라낸다. 크론에 넣어 알림용으로 쓴다. awk에서 int($5)는 "82%" 같은 문자열에서 숫자만 취한다.
df -hP -x tmpfs -x devtmpfs | awk 'NR>1 && int($5) >= 80 {print $6, $5}'
5) 지웠는데 용량이 안 도는 파일을 찾는다. df와 du의 합계가 크게 다르면 이걸 의심한다.
sudo lsof -nP +L1 2>/dev/null | grep -i deleted
함정과 주의점
큰 로그 파일을 rm 했는데 용량이 그대로다. 가장 자주 겪는 사고다. 리눅스는 파일을 참조하는 프로세스가 남아 있으면 디렉터리 엔트리만 지우고 데이터 블록은 유지한다. 애플리케이션이 그 로그 파일을 계속 열어 두고 있으면 30GB짜리를 지워도 df 수치는 1바이트도 안 줄어든다. 해결책은 해당 프로세스를 재시작하거나(정석), 급하면 파일 디스크립터를 통해 내용을 비우는 것이다.
# 애초에 rm 대신 이렇게 비우면 이 문제가 생기지 않는다
: > /var/log/myapp/app.log
Use%가 100%인데 Avail이 0이 아니고 Size와도 안 맞는다. ext4는 기본적으로 전체 블록의 5%를 root 전용으로 예약한다. 일반 사용자에게는 이미 꽉 찬 것으로 보이지만 root는 아직 쓸 수 있다. 1TB 볼륨이면 50GB가 묶여 있는 셈이라, 데이터 전용 볼륨에서는 tune2fs -m 1 /dev/vdc1처럼 줄이는 것이 보통이다. 단 tune2fs는 ext2/3/4 전용이라 위 예시의 xfs 볼륨(/dev/vdb1)에는 쓸 수 없고, xfs에는 이런 예약 블록 자체가 없다. 다만 루트 파일시스템에서는 이 예약이 시스템 복구 여지를 남겨 주므로 함부로 0으로 만들지 않는다.
디바이스 이름이 길면 출력이 두 줄로 접힌다. LVM이나 iSCSI 경로처럼 이름이 긴 경우 첫 컬럼만 한 줄을 차지하고 나머지가 다음 줄로 넘어간다. awk '{print $5}' 같은 파싱이 조용히 깨진다. 스크립트에서는 반드시 -P를 붙인다.
컨테이너 안의 df는 참고용이다. overlay 파일시스템으로 표시되는 값은 호스트 디스크 상황을 반영하므로, 컨테이너에 걸어 둔 스토리지 쿼터와는 다르다.
함께 보면 좋은 명령어
- du — df로 어느 마운트가 찼는지 알아낸 다음, 그 안에서 범인 디렉터리를 찾는다. 항상 짝으로 쓴다.
- lsof — 지웠지만 열려 있는 파일을 찾아낸다. df와 du가 안 맞을 때의 해답.
- ncdu — 디렉터리 용량을 대화형으로 파고든다. 별도 설치가 필요하지만 원인 추적이 훨씬 빠르다.