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