du와 df의 디스크 사용량 통계 차이 원인 분석

리눅스 시스템에서 디스크 사용량을 확인할 때 dudf 명령어를 자주 사용합니다. 하지만 두 명령어는 서로 다른 방식으로 디스크 사용량을 계산하기 때문에 결과가 일치하지 않는 경우가 많습니다.

예를 들어 다음과 같은 상황을 살펴보겠습니다:

# df -hT
Filesystem          Type   Size  Used Avail Use% Mounted on
/dev/sda2           ext4    18G  1.7G   15G  11% /
tmpfs               tmpfs  491M     0  491M   0% /dev/shm
/dev/sda1           ext4   239M   68M  159M  30% /boot
//192.168.0.124/win cifs   381G  243G  138G  64% /mnt

# du -sh / 2>/dev/null
244G    /

위 예제에서는 df는 루트 디렉토리(/)의 사용량을 1.7GB로 표시하고 있지만, du는 244GB를 반환하고 있습니다. 이처럼 두 도구의 결과가 크게 다를 수 있습니다.

파일 저장 및 삭제 메커니즘 이해

두 도구의 차이를 이해하려면 파일 시스템 내부 작동 방식을 알아야 합니다.

새로운 파일이 생성될 때:

  • inode 테이블에서 비어 있는 inode 번호를 할당받습니다.
  • 해당 inode 번호는 사용 중으로 표시됩니다.
  • 부모 디렉터리의 데이터 블록에 파일 이름과 inode 포인터를 추가합니다.
  • 데이터 블록 맵(bmap)에서 빈 블록을 찾아 파일 내용을 기록합니다.

파일이 삭제될 때:

  • inode 테이블에서 데이터 블록 포인터를 제거하여 외부 접근 불가능하게 만듭니다.
  • inode 맵(imap)에서 해당 inode 번호를 미사용 상태로 변경합니다.
  • 부모 디렉터리에서 파일 항목을 제거하여 파일을 보이지 않게 만듭니다.
  • bmap에서 해당 데이터 블록들을 미사용 상태로 표시합니다.

만약 파일이 삭제되었지만 여전히 어떤 프로세스가 해당 파일을 열고 있다면, 파일은 더 이상 보이지 않지만 실제 데이터는 여전히 존재합니다. 왜냐하면 bmap에서는 아직 데이터 블록들이 미사용 상태로 표시되지 않았기 때문입니다.

du 명령어의 동작 원리

du는 각 파일과 하위 디렉터리에 대해 stat() 시스템 호출을 수행하여 공간 사용량을 누적합니다. 따라서 대상이 많을수록 느립니다.

du의 특징:

  1. 마운트된 다른 파일 시스템 포함: 특정 디렉터리를 스캔할 때 그 아래 마운트된 다른 파일 시스템도 함께 계산합니다.
  2. 삭제된 파일 무시: 이미 삭제되어 stat()으로 찾을 수 없는 파일은 집계하지 않습니다.
  3. 크로스 파티션 지원: 여러 파티션에 걸쳐 있는 파일들의 총합을 계산할 수 있습니다.

예시:

# find / -type f -name "*.img" -print0 | xargs -0 du -csh 
19M     /boot/initramfs-2.6.32-504.el6.x86_64.img
13M     /mnt/linux工具/cirros-0.3.4-x86_64-disk.img
31M     total

df 명령어의 동작 원리

df는 각 파티션의 슈퍼블록(superblock) 정보를 읽어 사용 가능한 블록 수와 사용 중인 블록 수를 가져옵니다. 슈퍼블록 크기는 일반적으로 1KB이므로 매우 빠릅니다.

df의 특징:

  1. 개별 파티션 단위 통계: 마운트된 다른 파일 시스템은 별도로 취급하며, 포함하지 않습니다.
  2. 슈퍼블록 기반 계산: 지정된 파일이나 디렉터리는 해당 파티션 전체의 정보를 나타냅니다.
  3. 삭제되었으나 참조 중인 파일 포함: bmap이 업데이트되지 않은 파일도 사용량에 반영됩니다.

실제 예제:

# dd if=/dev/zero of=/temp_file bs=1M count=1000

# df -hT /
Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/sda2      ext4   18G  2.7G   14G  17% /

# du -sh --exclude="/mnt" / 2>/dev/null
2.7G    /

# tail -f /temp_file &
# rm -rf /temp_file

# du -sh --exclude="/mnt" / 2>/dev/null
1.8G    /

# df -hT /
Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/sda2      ext4   18G  2.7G   14G  17% /

파일이 삭제되었지만 프로세스가 계속 참조하고 있으므로 du에서는 제외되지만 df에서는 여전히 포함됩니다.

참조 중인 삭제된 파일을 확인하려면 다음 명령어를 사용할 수 있습니다:

# lsof | grep deleted
tail      14437      root    3r    REG   8,2 1048576000     7171 /temp_file (deleted)

해당 프로세스를 종료하면 df도 정확한 값을 보여줍니다.

# kill %1
# df -hT /
Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/sda2      ext4   18G  1.7G   15G  11% /

태그: linux file-system disk-usage du df

7월 16일 06:31에 게시됨