為什麼有這麼多不同的方法來衡量磁碟使用情況?
當我總結文件的大小時,我得到一個數字。如果我跑
du
,我會得到另一個數字。如果我du
在分區上的所有文件上執行,它與使用的聲明不匹配df
。為什麼我的文件總大小有這麼多不同的數字?電腦不能加嗎?說到添加:當我添加 的“Used”和“Available”列時
df
,我沒有得到總數。這個總數字小於我的分區大小。如果我把我的分區大小加起來,我就不會得到我的磁碟大小!是什麼賦予了?
加起來很容易。問題是,要添加許多不同的數字。
一個文件佔用多少磁碟空間?
基本思想是包含n字節的文件使用n字節的磁碟空間,加上一些控制資訊:文件的元數據(權限、時間戳等),以及系統需要的資訊的一些成本找到文件的儲存位置。然而,有許多並發症。
微觀並發症
將每個文件視為圖書館中的一系列書籍。較小的文件只構成一卷,但較大的文件由許多卷組成,就像百科全書一樣。為了能夠找到文件,有一個卡片目錄引用了每個卷。由於封面,每個卷都有一些成本。如果一個文件非常小,這個成本是比較大的。卡片目錄本身也佔用了一些空間。
更專業一點,在典型的簡單文件系統中,空間被劃分為blocks。典型的塊大小為 4KiB。每個文件佔用整數個塊。除非文件大小是塊大小的倍數,否則最後一個塊僅被部分使用。所以一個 1 字節的文件和一個 4096 字節的文件都佔用 1 個塊,而一個 4097 字節的文件佔用兩個塊。
ls
您可以使用或觀察這一點du
:如果您的文件系統具有 4KiB 塊大小,那麼ls -s
1du
字節文件將報告 4KiB。如果文件很大,則需要額外的塊來儲存組成文件的塊列表(這些是**間接塊;更複雜的文件系統可能會以範圍**的形式對此進行優化)。那些沒有顯示在
ls -l
GNU報告的文件大小中du --apparent-size
。du
和ls -s
,它報告磁碟使用而不是大小,確實說明了它們。一些文件系統嘗試重新使用最後一個塊中剩餘的空閒空間,以將多個文件尾部打包在同一個塊中。一些文件系統(例如ext4 自 Linux 3.8 起使用 0 塊儲存完全適合 inode 的小文件(僅幾個字節)。
宏觀並發症
通常,如上所示,報告的總大小
du
是文件使用的塊或範圍大小的總和。如果文件被壓縮,則報告的大小
du
可能會更小。Unix 系統傳統上支持一種粗略的壓縮形式:如果一個文件塊只包含空字節,那麼文件系統可以完全忽略該塊,而不是儲存一個零塊。像這樣帶有省略塊的文件稱為**稀疏文件**。當文件包含大量空字節時,不會自動創建稀疏文件,應用程序必須安排文件變得稀疏。高級並發症
非常現代的文件系統(例如 zfs 和 btrfs)的兩個主要特性使得文件大小和磁碟使用之間的關係更加遙遠:快照和重複數據刪除。
**快照**是文件系統在特定日期的凍結狀態。支持此功能的文件系統可以包含在不同日期拍攝的多個快照。當然,這些快照佔據了空間。在一種極端情況下,如果您從文件系統的活動版本中刪除所有文件,則如果剩餘快照,文件系統將不會變為空。
自快照以來或在拍攝兩個快照之間未更改的任何文件或塊都相同地存在於快照和活動版本或其他快照中。這是通過寫時複製實現的。在某些極端情況下,由於可用空間不足,刪除完整文件系統上的文件可能會失敗——因為刪除該文件需要在目錄中製作一個塊的副本,而且即使是那個塊也沒有更多空間了。
**重複數據刪除**是一種儲存優化技術,包括避免儲存相同的塊。對於典型數據,尋找重複數據並不總是值得付出努力。zfs和btrfs都支持重複數據刪除作為可選功能。
為什麼
du
總和與文件大小的總和不同?正如我們在上面看到的,
du
每個文件報告的大小通常是文件使用的塊或範圍大小的總和。請注意,預設情況下,ls -l
以字節為單位列出大小,但du
以 KiB 為單位列出大小,或者在一些更傳統的系統上以 512 字節單位(扇區)列出大小(du -k
強制使用千字節)。大多數現代 unices 支持ls -lh
並du -h
使用“人類可讀”的數字,使用 K、M、G 等(對於 KiB、MiB、GiB)就足夠了(對於 KiB、MiB、GiB)。在目錄上執行
du
時,它會匯總目錄樹中所有文件的磁碟使用情況,包括目錄本身。目錄包含數據(文件名和指向文件元數據所在位置的指針),因此它需要一些儲存空間。一個小目錄將佔用一個塊,一個較大的目錄將需要更多塊。目錄使用的儲存量有時不僅取決於它包含的文件,還取決於插入它們的順序以及刪除某些文件的順序(對於某些文件系統,這可能會留下漏洞——磁碟空間和性能之間的折衷),但差異會很小(這里和那裡有一個額外的塊)。當你跑ls -ld /some/directory
,目錄的大小被列出。(請注意,輸出頂部的“total NNN”行ls -l
是一個不相關的數字,它是所列項目的塊大小的總和,以 KiB 或扇區表示。)請記住,
du
其中包括不顯示的**點文件**,除非您使用or選項。ls``-A``-a
有時
du
報告少於預期的總和。如果目錄樹中有**硬連結**du
,就會發生這種情況:每個文件只計算一次。如果文件有N個硬連結,則使用du -l
switch 將文件計數N次。在某些文件系統(如
ZFS
Linux)上,du
不報告文件的擴展屬性佔用的完整磁碟空間。請注意,如果目錄下有掛載點,除非給出選項
du
,否則也會計算這些掛載點上的所有文件。-x
因此,例如,如果您想要根文件系統中文件的總大小,請執行du -x /
,而不是du /
.如果文件系統掛載到非空目錄,則該目錄中的文件被掛載的文件系統隱藏。他們仍然佔據他們的空間,但
du
不會找到他們。已刪除的文件
當一個文件被刪除時,這只會刪除目錄條目,不一定是文件本身。為了真正刪除文件並回收其磁碟空間,需要兩個條件:
- 文件的連結計數必須降至 0:如果一個文件有多個硬連結,刪除一個不會影響其他的。
- 只要文件被某個程序打開,數據就會保留。只有當所有程序都關閉該文件時,該文件才會被刪除。輸出
fuser -m
或lsof
掛載點包括在該文件系統上打開文件的程序,即使該文件已被刪除。- 即使沒有程序打開已刪除的文件,如果該文件是
loop
設備的後端,則可能不會回收該文件的空間。losetup -a
(asroot
) 可以告訴您loop
目前設置了哪些設備以及在什麼文件上。losetup -d
在回收磁碟空間之前,必須銷毀循環設備(使用)。如果您在某些文件管理器或 GUI 環境中刪除文件,它可能會被放入可以取消刪除的垃圾區域。只要文件可以被取消刪除,它的空間仍然被消耗。
這些數字究竟來自
df
什麼?典型的文件系統包含:
僅報告第一種
du
。說到df
“已用”、“可用”和“總”列的內容取決於文件系統(當然,已使用的塊(包括間接塊)總是在“使用”列中,未使用的塊總是在“可用”列)。ext2/ext3/ext4 中的文件系統為 root 使用者**保留5% 的空間。**這在根文件系統上很有用,可以在系統填滿時保持系統執行(特別是對於日誌記錄,以及讓系統管理員在解決問題時儲存一些數據)。即使對於諸如 的數據分區
/home
,保留該保留空間也很有用,因為幾乎已滿的文件系統容易產生碎片。Linux 試圖通過在寫入文件時預先分配許多連續塊來避免碎片(這會減慢文件訪問速度,尤其是在硬碟等旋轉機械設備上),但如果連續塊不多,則無法工作.傳統的文件系統,包括 ext4,但不包括 btrfs,在創建文件系統時保留固定數量的inode。這顯著簡化了文件系統的設計,但缺點是需要適當調整 inode 的數量:inode 太多會浪費空間;如果 inode 太少,文件系統可能會在空間不足之前用完 inode。該命令
df -i
報告有多少 inode 正在使用以及有多少可用(該概念不適用的文件系統可能報告 0)。在包含 ext2/ext3/ext4 文件系統的捲上執行
tune2fs -l
會報告一些統計資訊,包括空閒 inode 和塊的總數和數量。另一個可能混淆問題的特性是子卷(在btrfs和 zfs 中以datasets的名稱支持)。多個子卷共享相同的空間,但具有不同的目錄樹根。
如果一個文件系統掛載在網路上(NFS、Samba 等)並且伺服器導出該文件系統的一部分(例如,伺服器有一個
/home
文件系統,並導出/home/bob
),那麼df
在客戶端上會反映整個文件系統的數據,而不是僅用於導出並安裝在客戶端上的部分。什麼在使用我磁碟上的空間?
正如我們在上面看到的,報告的總大小
df
並不總是考慮文件系統的所有控制數據。如果需要,使用文件系統特定的工具來獲取文件系統的確切大小。例如,使用 ext2/ext3/ext4,執行tune2fs -l
塊大小乘以塊數。創建文件系統時,它通常會填滿封閉分區或卷上的可用空間。有時,當您移動文件系統或調整捲大小時,您最終可能會得到一個較小的文件系統。
在 Linux 上,
lsblk
很好地概述了可用的儲存卷。有關其他資訊或如果您沒有lsblk
,請使用專門的捲管理或分區工具來檢查您有哪些分區。在 Linux 上,有lvs
,vgs
,pvs
用於LVM,fdisk
用於傳統 PC 風格 (“MBR”) 分區(以及最近系統上的 GPT),gdisk
用於GPT分區,disklabel
用於 BSD 磁碟標籤,Parted等。在 Linux 下,cat /proc/partitions
給出了一個快速總結。典型的安裝至少有兩個分區或作業系統使用的捲:一個文件系統(有時更多)和一個交換卷。有些電腦有一個包含BIOS或其他診斷軟體的分區。具有UEFI的電腦具有專用的引導載入程序分區。
最後,請注意大多數電腦程序使用基於 1024 = 2 10的冪的單位(因為程序員喜歡二進制和 2 的冪)。所以 1 kB = 1024 B, 1 MB = 1048576 B, 1 GB = 1073741824, 1 TB = 1099511627776 B, … 官方稱這些單位為kibibyte KiB, mebibyte MiB 等,但大多數軟體只報告 k 或 kB, M 或 MB 等。另一方面,硬碟製造商系統地使用公制(以 1000 為單位)。所以 1 TB 驅動器只有 931 GiB 或 0.904 TiB。