[Linux] df, du 명령어 차이점 & 차이날 때 해결 방법

수정일 화, 11월 4 시간: 3:11 PM

안녕하세요 베스핀글로벌 클라우드 기술지원팀입니다.

Linux에서 디스크 사용량을 확인하는 두 가지 핵심 명령어인 df와 du에 대해 알아보겠습니다.

df와 du란 무엇인가?


df (disk free) 명령어는 파일 시스템 단위로 디스크 사용량을 확인하는 도구입니다. 파일 시스템의 메타데이터를 조회하여 마운트된 디스크의 전체 크기, 사용 중인 공간, 사용 가능한 공간, 사용률, 마운트 위치 등의 정보를 제공합니다.

du (disk usage) 명령어는 특정 디렉토리나 파일을 기준으로 실제 디스크 사용량을 확인하는 도구입니다. 파일 트리를 순회하면서 각 파일과 디렉토리가 실제로 사용하는 디스크 블록을 계산합니다.

기본 사용법 및 실행 예시

df 명령어 사용 예시

# 사람이 읽기 쉬운 형식으로 출력
$ df -h /var
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        50G   35G   13G  74% /

# inode 사용량 확인
$ df -i /var
Filesystem      Inodes  IUsed   IFree IUse% Mounted on
/dev/sda1      3276800 145234 3131566    5% /

du 명령어 사용 예시

# 특정 디렉토리의 총 사용량 확인
$ du -sh /var
28G     /var

# 하위 디렉토리별 사용량 확인
$ du -h --max-depth=1 /var
5.2G    /var/log
12G     /var/lib
8.1G    /var/cache
2.7G    /var/www
28G     /var

위 예시에서 df는 35G 사용, du는 28G로 표시되어 약 7G의 차이가 발생했습니다. 이러한 차이가 왜 발생하는지 알아보겠습니다.

df와 du의 동작 원리 차이

두 명령어는 디스크 사용량을 계산하는 방식이 근본적으로 다릅니다.

df 명령어:

  • 파일 시스템의 슈퍼블록(superblock) 메타데이터를 조회
  • 전체 블록 수에서 사용 가능한 블록 수를 빼서 계산
  • 파일 시스템 수준에서 할당된 모든 공간을 포함

du 명령어:

  • 파일 트리를 실제로 순회(traverse)
  • stat() 시스템 호출로 각 파일의 블록 수를 확인
  • 디렉토리 구조상 접근 가능한 파일만 계산

이러한 계산 방식의 차이로 인해 두 명령어의 결과가 다를 수 있습니다.

df와 du 차이가 발생하는 주요 원인

1. 삭제된 파일이 프로세스에서 사용 중인 경우 (가장 흔한 원인)

파일이 삭제되었지만 해당 파일을 열고 있는 프로세스가 존재하면, 파일 디스크립터가 닫힐 때까지 디스크 공간이 실제로 해제되지 않습니다. 주로 로그 파일에서 자주 발생합니다.

확인 방법:

# 삭제된 파일을 사용 중인 프로세스 확인
$ lsof -n | grep deleted
httpd     1234  root    5w   REG  253,0  5368709120  131075 /var/log/httpd/access.log (deleted)
mysqld    5678  mysql   3w   REG  253,0  2147483648  262144 /var/lib/mysql/binlog.000123 (deleted)

출력 해석:

  • httpd 프로세스(PID: 1234)가 삭제된 /var/log/httpd/access.log 파일을 약 5GB 크기로 여전히 사용 중
  • mysqld 프로세스(PID: 5678)가 삭제된 바이너리 로그 파일을 약 2GB 크기로 사용 중
  • 파일 디스크립터 번호: httpd는 5번, mysqld는 3번

해결 방법:

# 방법 1: 프로세스 재시작 (권장)
$ systemctl restart httpd
$ systemctl restart mysql

# 방법 2: 파일 디스크립터를 직접 비우기 (재시작이 불가능한 경우)
# 프로세스를 중단하지 않고 파일 내용만 비움
$ > /proc/1234/fd/5
$ > /proc/5678/fd/3

# 방법 3: 특정 프로세스만 종료
$ kill -9 1234

예방 방법:

  • 로그 로테이션 설정 시 copytruncate 옵션 사용
  • 애플리케이션이 로그 파일을 주기적으로 재오픈하도록 구성

참고: Red Hat - Understanding file deletion behavior https://access.redhat.com/solutions/2316

2. Sparse 파일 (희소 파일)

Sparse 파일은 실제로 데이터가 기록되지 않은 영역을 포함하는 파일로, 논리적 크기와 실제 디스크 사용량이 다릅니다.

Sparse 파일 예시:

# 10GB 크기의 sparse 파일 생성
$ dd if=/dev/zero of=sparse.img bs=1 count=0 seek=10G
0+0 records in
0+0 records out
0 bytes copied, 0.000123 s, 0.0 kB/s

# 파일 크기 확인
$ ls -lh sparse.img
-rw-r--r-- 1 root root 10G Nov  4 10:00 sparse.img  # 논리적 크기: 10G

# 실제 디스크 사용량 확인
$ du -h sparse.img
0       sparse.img  # 실제 사용량: 0

# 또는 --apparent-size 옵션으로 논리적 크기 확인
$ du -h --apparent-size sparse.img
10G     sparse.img

Sparse 파일 확인 방법:

# Sparse ratio가 1.0 미만인 파일 찾기
$ find /var -type f -printf "%S %p\n" | awk '$1 < 1.0' | head -10
0.5 /var/lib/mysql/ibdata1
0.3 /var/log/journal/system.journal
0.8 /var/lib/libvirt/images/vm1.qcow2

Sparse 파일이 많은 경우 du가 df보다 작은 값을 보여줍니다.

참고: GNU Coreutils - du invocation https://www.gnu.org/software/coreutils/manual/html_node/du-invocation.html

3. 파일시스템 예약 공간

ext4 파일시스템은 기본적으로 전체 용량의 5%를 root 사용자를 위해 예약합니다. 이는 시스템이 디스크가 가득 찼을 때도 관리 작업을 수행할 수 있도록 하기 위함입니다.

예약 공간 확인:

# 파일시스템 정보 확인
$ tune2fs -l /dev/sda1 | grep -i "block count"
Block count:              13107200
Reserved block count:     655360

# 예약 비율 확인
$ tune2fs -l /dev/sda1 | grep -i "reserved"
Reserved block count:     655360
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)

위 예시에서는 약 655,360 블록(약 2.5GB, 블록 크기가 4KB인 경우)이 예약되어 있습니다.

예약 공간 조정:

# 예약 비율을 1%로 변경 (대용량 디스크에서 권장)
$ tune2fs -m 1 /dev/sda1
tune2fs 1.45.5 (07-Jan-2020)
Setting reserved blocks percentage to 1% (131072 blocks)

# 예약 블록을 특정 개수로 설정
$ tune2fs -r 131072 /dev/sda1

참고: Red Hat - Reserved space for root on ext4 https://access.redhat.com/solutions/1542

4. Hard Link

Hard link가 있는 파일의 경우, du는 각 hard link를 별도로 계산할 수 있습니다.

Hard link 확인:

# Hard link가 2개 이상인 파일 찾기
$ find /var -type f -links +1 -ls
131075   100000 -rw-r--r--   2 root  root   102400000 Nov  4 10:00 /var/data/file1.dat
131075   100000 -rw-r--r--   2 root  root   102400000 Nov  4 10:00 /var/backup/file1.dat

# 같은 inode 번호(131075)를 가진 파일들은 동일한 데이터를 가리킴

du는 기본적으로 hard link를 처음 만났을 때만 계산하지만, 여러 디렉토리를 별도로 실행하면 중복 계산될 수 있습니다.

올바른 계산 방법:

# hard link를 한 번만 계산
$ du -sh --count-links /var

참고: GNU Coreutils - du and hard links https://www.gnu.org/software/coreutils/manual/htmlnode/du-invocation.html#index-002d002dcount002dlinks

5. 마운트 포인트

du는 기본적으로 다른 파일시스템으로 마운트된 디렉토리를 순회하지 않습니다.

마운트 포인트 확인:

# 특정 경로 하위의 마운트 포인트 확인
$ mount | grep /var
/dev/sdb1 on /var/lib/mysql type ext4 (rw,relatime)
/dev/sdc1 on /var/log type ext4 (rw,relatime)

# 마운트 포인트를 포함하여 계산
$ du -sh -x /var  # -x: 같은 파일시스템만 계산
$ du -sh /var     # 모든 마운트 포인트 포함

6. 메타데이터 오버헤드

파일시스템은 inode, 디렉토리 엔트리, 저널 등의 메타데이터를 위한 공간을 사용합니다. df는 이를 포함하지만 du는 포함하지 않습니다.

# inode 사용량 확인
$ df -i /var
Filesystem      Inodes  IUsed   IFree IUse% Mounted on
/dev/sda1      3276800 145234 3131566    5% /

# 작은 파일이 많을수록 메타데이터 오버헤드 증가
$ find /var -type f | wc -l
145234  # 약 145,000개의 파일

참고: Ext4 Disk Layout https://ext4.wiki.kernel.org/index.php/Ext4DiskLayout

트러블슈팅 플로우

df와 du의 차이가 크게 발생했을 때 다음 순서대로 확인하세요:

체크리스트

# 1. 삭제된 파일이 프로세스에서 사용 중인지 확인 (가장 먼저 확인)
$ lsof -n | grep deleted

# 2. 마운트된 서브 디렉토리가 있는지 확인
$ mount | grep /target/path
$ findmnt /target/path

# 3. Sparse 파일 존재 여부 확인
$ find /var -type f -printf "%S %p\n" | awk '$1 < 1.0' | head -20

# 4. Hard link 파일 존재 여부 확인
$ find /var -type f -links +1 -ls | head -20

# 5. 파일시스템 예약 공간 확인
$ tune2fs -l /dev/sda1 | grep -i "reserved block"

# 6. 작은 파일이 많아 메타데이터 오버헤드가 큰지 확인
$ find /var -type f | wc -l
$ df -i /var

일반적인 해결 순서

  1. 삭제된 파일 문제 해결 (가장 흔함)
    • lsof -n | grep deleted 실행
    • 해당 프로세스 재시작 또는 파일 디스크립터 비우기
  2. sync 명령어 실행

    $ sync
    

    버퍼 캐시에 있는 데이터를 디스크에 기록

  3. 재부팅이 필요한 경우

    • 프로세스를 재시작할 수 없는 경우
    • 여러 프로세스가 복잡하게 얽혀있는 경우
  4. 파일시스템 체크 (마지막 수단)

    # 파일시스템을 언마운트하고 체크
    $ umount /dev/sda1
    $ fsck -f /dev/sda1
    

실무 사례 예시

사례 1: 로그 파일 삭제 후에도 디스크 공간이 해제되지 않음

# 현상
$ df -h /var
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       100G   95G    5G  95% /

$ du -sh /var
60G     /var

# 35GB 차이 확인

# 원인 확인
$ lsof -n | grep deleted | grep /var
java      12345  tomcat   3w   REG  253,0  37580963840  /var/log/tomcat/catalina.out (deleted)

# 해결
$ systemctl restart tomcat
# 또는
$ > /proc/12345/fd/3

# 결과 확인
$ df -h /var
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       100G   60G   40G  60% /

# 35GB가 해제됨!

사례 2: MySQL 바이너리 로그 문제

# 현상
$ df -h /var/lib/mysql
Filesystem      Size  Used Avail Use% Mounted on
/dev/sdb1       200G  180G   20G  90% /var/lib/mysql

$ du -sh /var/lib/mysql
120G    /var/lib/mysql

# 원인 확인
$ lsof -n | grep deleted | grep mysql
mysqld    5678  mysql   5w   REG  253,1  64424509440  /var/lib/mysql/mysql-bin.000123 (deleted)

# 해결 (재시작이 어려운 경우 파일 내용 비우기)
$ > /proc/5678/fd/5

# 또는 MySQL 명령으로 로그 퍼지 후 재시작
$ mysql -e "PURGE BINARY LOGS BEFORE NOW();"
$ systemctl restart mysql

정상적인 차이 범위

다음과 같은 경우는 정상적인 차이로 간주할 수 있습니다:

  • 1-5% 차이: 파일시스템 예약 공간, 메타데이터 오버헤드로 인한 정상 범위
  • 5-10% 차이: Sparse 파일, hard link 등이 있을 수 있으나 대부분 정상
  • 10% 이상 차이: 삭제된 파일이 프로세스에서 사용 중이거나 문제가 있을 가능성 높음


df와 du의 올바른 사용 목적

df를 사용해야 하는 경우:

  • 파일시스템 전체의 사용 가능한 공간 확인
  • 디스크 용량 모니터링 및 알람 설정
  • 시스템 전체의 디스크 상태 빠른 확인

du를 사용해야 하는 경우:

  • 특정 디렉토리나 애플리케이션의 디스크 사용량 확인
  • 용량을 많이 차지하는 디렉토리 찾기
  • 디스크 정리 대상 식별

결론

df와 du는 디스크 사용량을 계산하는 방식과 목적이 다른 도구입니다. 두 명령어의 차이가 크게 발생하는 가장 흔한 원인은 삭제된 파일이 프로세스에서 여전히 사용 중인 경우이며, 이는 lsof -n | grep deleted명령으로 쉽게 확인하고 해결할 수 있습니다.

실무에서는 용도에 맞는 도구를 선택하여 사용하는 것이 중요합니다. df는 파일시스템 전체의 가용 공간을 빠르게 파악하는데 사용하고, du는 특정 디렉토리의 상세한 사용량을 분석하는데 사용하면 됩니다.

참고 자료

  1. Red Hat - du vs df: https://www.redhat.com/sysadmin/du-vs-df
  2. OSTechNix - Understanding df and du: https://ostechnix.com/understanding-df-and-du-commands-in-linux/
  3. Cyberciti - Why df and du reports different output: https://www.cyberciti.biz/tips/freebsd-why-command-df-and-du-reports-different-output.html
  4. GNU Coreutils Manual - df: https://www.gnu.org/software/coreutils/manual/html_node/df-invocation.html
  5. GNU Coreutils Manual - du: https://www.gnu.org/software/coreutils/manual/html_node/du-invocation.html
  6. Linux man pages - lsof: https://man7.org/linux/man-pages/man8/lsof.8.html
  7. Ext4 Wiki - Disk Layout: https://ext4.wiki.kernel.org/index.php/Ext4DiskLayout
  8. Red Hat - File deletion behavior: https://access.redhat.com/solutions/2316

아티클이 유용했나요?

훌륭합니다!

피드백을 제공해 주셔서 감사합니다.

도움이 되지 못해 죄송합니다!

피드백을 제공해 주셔서 감사합니다.

아티클을 개선할 수 있는 방법을 알려주세요!

최소 하나의 이유를 선택하세요
CAPTCHA 확인이 필요합니다.

피드백 전송

소중한 의견을 수렴하여 아티클을 개선하도록 노력하겠습니다.