
안녕하세요, 오픈소스컨설팅에서 리눅스를 담당하고 있는 강주희입니다.
리눅스에서 ls 와 df 로 파일의 크기를 확인했을 때 크기가 달랐던 경험 있으신가요? ls, df, du 와 같은 유틸리티(utility)는 표현 방식의 차이가 있기 때문입니다. 이번 포스팅에서는 관련하여, 아래 내용들을 살펴보겠습니다.
- 각 유틸리티의 표현 방식의 차이를 알아보고,
- 각 유틸리티마다 같은 파일의 크기가 다르게 나타나는 경우와
- 그 이유를 살펴보겠습니다.
각 유틸리티 별 표현 방식
ls, du, df 와 같은 유틸리티가 파일이나 디스크의 크기를 표현하는 방식은 다음과 같습니다.
ls
: 블록이 실제로 파일에 할당되었는지 여부에 관계없이 파일 끝과 파일 시작 사이의 차이를 기반으로 개별 파일에 대한 데이터를 제공합니다.du
: 개별 파일에 실제로 할당된 블록을 보여줍니다.df
: inode 및 기타 메타 데이터를 포함하여 전체 파일 시스템에 할당된 블록을 보여줍니다.
각 유틸리티 마다 같은 파일의 크기가 다르게 나타나는 경우
“파일의 크기”와 “파일이 디스크에 차지하는 공간”은 다를 수 있습니다.
파일은 연속적인 null byte(0x00)를 포함할 경우, 디스크 공간을 효율적으로 사용하기 위해서 빈 블록을 디스크에 물리적으로 쓰지 않을 수 있습니다. 이러한 파일을 Sparse File 이라고 합니다. Sparse File의 저장 방식을 그림으로 표현하지면 다음과 같습니다.

[출처] http://wikipedia.org
Sparse File는 null byte를 디스크에 저장하지 않는 대신 메타데이터로 나타냅니다. 실제 디스크에는 null byte가 아닌 데이터만 저장됩니다. 파일 시스템에서 Sparse File을 읽을 때는 빈 블록을 표현한 메타데이터를 런타임에 null byte로 채워진 실제 블록으로 변환합니다. 따라서 파일이 Sparse File 이라면 “파일시스템이 인식하는 파일의 크기”가 “실제 파일이 차지하는 디스크의 공간” 보다 크게 표현될 수 있습니다.
파일시스템이 인식하는 파일의 크기는 명령어 ll, ls 로 확인하고, 파일이 차지하는 디스크 공간은 df, du 명령어로 확인합니다. 간단한 테스트로 Sparse file을 확인해 보겠습니다.
1. 200MB의 Sparse File을 생성합니다.
[root@test ~]# dd if=/dev/zero of=sparse.img bs=1M count=1 seek=200
[root@test ~]# ll -lh sparse.img
-rw-r--r-- 1 root root 201M 7월 28 15:33 sparse.img
2. 원본 파일에서 null byte(0x00)를 sparse file 로 생성하지 않도록 cp 유틸리티의 옵션(–sparse=never)을 지정하여 복사본을 만듭니다.
[root@test ~]# cp --sparse=never sparse.img unsparse.img
3. 파일시스템에서 인식하는 파일의 크기를 확인합니다.
파일시스템에서는 두 파일을 같은 크기로 인식합니다.
[root@test ~]# ll -lh *.img
-rw-r--r-- 1 root root 201M 7월 28 15:33 sparse.img --> 원본 파일
-rw-r--r-- 1 root root 201M 7월 28 15:35 unsparse.img --> sparse 제거 파일
4. 그러나 두 파일이 디스크에서 차지하는 공간은 다릅니다.
[root@test ~]# du -h *.img
1.0M sparse.img --> 원본 파일
201M
unsparse.img --> sparse 제거 파일
5. ls 에 -s 옵션을 사용하면 파일의 크기와 디스크에 차지하는 공간을 모두 확인할 수 있습니다.
[root@test ~]# ls -lhs *.img
1.0M -rw-r--r-- 1 root root 201M 7월 28 15:33 sparse.img
201M -rw-r--r-- 1 root root 201M 7월 28 15:35 unsparse.img
^ ^
디스크 공간 파일의 크기
6. stat 을 통해서도 확인할 수 있습니다.
[root@test ~]# stat *.img
File: ‘sparse.img’
Size: 210763776 Blocks: 2048 IO Block: 4096 regular file
Device: fd00h/64768d Inode: 538226370 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2023-06-26 16:08:38.683849761 +0900
Modify: 2023-06-26 16:07:33.106253296 +0900
Change: 2023-06-26 16:07:33.106253296 +0900
Birth: -
File: ‘unsparse.img’
Size: 210763776 Blocks: 411648 IO Block: 4096 regular file
Device: fd00h/64768d Inode: 538226381 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2023-06-26 16:08:38.580848824 +0900
Modify: 2023-06-26 16:08:38.683849761 +0900
Change: 2023-06-26 16:08:38.683849761 +0900
Birth: -
Sparse File 을 사용할 때 주의할 점
cp, rsync, dd 유틸리티를 사용하여 Sparse File을 복사할 때 명시적으로 지정해주지 않으면 디스크에 할당되지 않은 null byte을 포함하여 파일의 압축되지 않은 전체 크기를 복사할 수 있습니다.
Sparse 속성을 유지한 채로 파일을 복사하려면 다음과 같이 Sparse File을 인식하는 명령을 사용해야 합니다.
# cp --sparse=always /source/filename /destination/filename
# dd if=/source/filename of=/destination/filename conv=sparse
# rsync -S /source/filename <username>@hostname:/destination/filename
scp 유틸리티는 Sparse 속성을 지원하지 않기 때문에 scp로 파일을 복사하면 “non-sparse” 파일이 생성됩니다.
Sparse File이 사용되는 케이스
- Thin Provisioned Virtual Disks
- 가상 머신 디스크 파일이 Thin provisioning 으로 구성된 파일이라면 해당 파일은 Sparse File 를 저장할 수 있습니다. 디스크에는 할당한 파일 크기가 아닌 실제 사용한 데이터 크기만큼 물리 공간을 차지합니다.
- vmcore
- 덤프 파일 크기를 줄이기 위해 vmcore 덤프 파일에 대해 Sparse File을 사용하도록 구성할 수 있습니다.
3줄 요약
- Sparse File은 디스크 공간을 효율적으로 사용하는 일반적인 방법입니다.
- ls 명령어는 “파일시스템 상의 파일의 크기”를 나타내고 df, du 명령어는 “디스크에 차지하는 파일의 크기”는 나타냅니다. 따라서 같은 파일이라도 Sparse File 속성을 가진 파일이라면 ls와 df로 확인한 크기가 다를 수 있습니다.
- 파일을 Sparse 속성을 유지한 채로 복사하려면 유틸리티 옵션으로 명시적으로 지정해주어야 합니다.
One reply on “[Linux 인사이트] ls 명령어를 사용할 때 이건 꼭 조심하세요!”
주희님!! 오랜만이네요 반갑습니다 ^^