在 GNU/Linux 中刪除硬連結,以及 inode 的故事
大家好,我是無能。
很久沒有使用 ln 命令建立連結了,結果不小心忘記刪除 -s 選項,導致建立了硬連結,所以現在要來刪除這些不必要的硬連結。
建立硬連結
執行不帶選項的 ln 命令會建立硬連結。
alleycat:[haturatu]:~/git/hardlink$ ls
alleycat:[haturatu]:~/git/hardlink$ touch hardlink1
alleycat:[haturatu]:~/git/hardlink$ echo "You are an idiot" >> hardlink1
alleycat:[haturatu]:~/git/hardlink$ cat hardlink1
You are an idiot
alleycat:[haturatu]:~/git/hardlink$ ls -la
合計 12
drwxr-xr-x 2 haturatu haturatu 4096 1月 12 15:00 .
drwxr-xr-x 114 haturatu haturatu 4096 1月 12 15:00 ..
-rw-r--r-- 1 haturatu haturatu 17 1月 12 15:01 hardlink1
我嘗試如上所示建立了一個檔案。
alleycat:[haturatu]:~/git/hardlink$ ln hardlink1 hardlink2
alleycat:[haturatu]:~/git/hardlink$ ls -la
合計 16
drwxr-xr-x 2 haturatu haturatu 4096 1月 12 15:02 .
drwxr-xr-x 114 haturatu haturatu 4096 1月 12 15:00 ..
-rw-r--r-- 2 haturatu haturatu 17 1月 12 15:01 hardlink1
-rw-r--r-- 2 haturatu haturatu 17 1月 12 15:01 hardlink2
這樣就建立了一個硬連結。
然後,我們來看看下面的標準輸出。
-rw-r--r-- 2 haturatu haturatu 17 1月 12 15:01 hardlink1
-rw-r--r-- 2 haturatu haturatu 17 1月 12 15:01 hardlink2
這個 -rw-r--r-- 2 中的 2 就是硬連結的數量。與建立硬連結之前相比,您可以確認這個值增加了。
而且,這畢竟只是連結,所以不會佔用實際的磁碟空間。它儲存單一資料,inode 號碼相同,指向同一個檔案。
使用 -i 選項確認 inode 號碼。
alleycat:[haturatu]:~/git/hardlink$ ls -lia
合計 16
13238408 drwxr-xr-x 2 haturatu haturatu 4096 1月 12 15:02 .
11406555 drwxr-xr-x 114 haturatu haturatu 4096 1月 12 15:00 ..
13265123 -rw-r--r-- 2 haturatu haturatu 17 1月 12 15:01 hardlink1
13265123 -rw-r--r-- 2 haturatu haturatu 17 1月 12 15:01 hardlink2
什麼是 inode?
這畢竟取決於檔案系統,所以上面是在 GNU/Linux 環境下。如果是 BSD 類的檔案系統,可能是 vnode,ZFS 可能是 znode 等,有些許不同,但從歷史上看,可以理解為是原始 UNIX 檔案系統的擴展。
而且,與符號連結不同,硬連結即使刪除 hardlink1,hardlink2 仍然存在;即使刪除 hardlink2,hardlink1 仍然存在。從這一點來說,似乎可以解釋為檔案系統本身管理著該檔案,但這仍然有點難以理解,對吧?
然而,這樣看來,硬連結很方便,但符號連結可以引用不同磁碟上的檔案,而硬連結不能在不同磁碟上建立。
簡單來說,根據前面的解釋,檔案系統是基於單一磁碟的 inode 基準,所以如果是不同磁碟,則超出該檔案系統的管轄範圍,無法從層次結構上引用。
因此,如果檔案存在於不同磁碟上,就需要建立符號連結。
而且,從檔案系統的角度來看,這在磁碟復原、恢復作業時被廣泛使用,透過參考過去的 inode 資訊來識別哪些 inode 號碼的檔案被建立或刪除。
這裡有一個陷阱:如果檔案被覆寫,這個 inode 號碼也會被更新。這意味著在建立備份腳本等時,可能需要注意建立不會包含覆寫處理的腳本。(我曾經犯過一次錯誤)
識別具有相同 inode 號碼的檔案
可以使用 find 命令進行確認。
alleycat:[haturatu]:~/git/hardlink$ find . -inum 13265123
./hardlink2
./hardlink1
那麼,現在我來刪除 hardlink1。
alleycat:[haturatu]:~/git/hardlink$ rm -i hardlink1
rm: 通常檔案 'hardlink1' を削除しますか? y
alleycat:[haturatu]:~/git/hardlink$ ls -lai
合計 12
13238408 drwxr-xr-x 2 haturatu haturatu 4096 1月 12 15:23 .
11406555 drwxr-xr-x 114 haturatu haturatu 4096 1月 12 15:00 ..
13265123 -rw-r--r-- 1 haturatu haturatu 17 1月 12 15:01 hardlink2
alleycat:[haturatu]:~/git/hardlink$ cat hardlink2
You are an idiot
這樣,硬連結的值也變成了 1,並且確認了原本透過 ln hardlink1 hardlink2 建立的 hardlink1 連結,以及擁有與 hardlink1 相同資訊的 hardlink2 存在並包含相同的資料。
實用方面
雖然很久沒碰了,但如果想在同一個磁碟內複製大檔案但又想減少磁碟消耗,似乎使用硬連結會比較好。
嗯,這可能不是經常會刻意使用的東西,但它能讓人稍微了解檔案系統的結構,所以我覺得很有趣。
那麼,下次再見。
請多指教。