最近在安裝壹台測試機,由於要架設好幾個站台,每個站台的程式部分大概有 20MB 左右而已,但是搭配著網站進行測試的相關檔案卻有將近 3GB 之多,為了可以順利測試網站這些檔案都必須存在,如果真的複製好幾份的話主機就會頓時浪費許多磁碟空間,這時就可以多加利用建立 檔案連結、目錄連結 或 目錄連接 (Junction) 的方式有效減少硬碟空間。
由於 Windows 主機普遍都是採用 NTFS 檔案系統,而在 NTFS 檔案系統裡有關「連結」的種類有好幾款,我第一次接觸時也是霧裡看花,不常用的人真的會搞不清楚這幾種的差別,我先來簡單介紹一下:
在 NTFS 檔案系統裡有種物件類型稱為 NTFS reparse point (不太知道怎樣翻譯這名詞),這是從 NTFS v3.0 也就是 Windows 2000 開始就有的東西,他可以延伸檔案系統對檔案處理的方式,只要在特定目錄或檔案上添加所謂的 Reparse Point Tags 就能讓作業系統或應用程式知道要去哪裡找檔案內容。
簡單來說,NTFS reparse point 可區分成兩大類:
硬式連結 ( Hard Links )
這種連結類型歷史悠久,從 NT 4.0 開始就存在了,他有一個很明顯的限制,就是要建立這種硬式連結其實體檔案與連結都必須位於同一個磁碟機裡,就算是同一顆硬碟不同分割區也不能跨越。
硬式連結在連接檔案時 (注意: NTFS 不支援目錄硬式連結),所連結的對象並不是「參照檔案的路徑」,而是「參照檔案的 NTFS 檔案位置」,如下圖示代表著你建立完 LINK A.TXT 與 LINK B.TXT 這兩個硬式連結到特定檔案後,他實際上所指向的是磁碟實體的資料位置,並不會記憶建立連結時的檔案路徑與名稱,就算你刪除了原本建立的那個檔案,其資料也不會消失,LINK A.TXT 與 LINK B.TXT 這兩個硬式連結一樣能存取到檔案內容,只有當所有連結到實體磁碟位置的硬式連結都不見了,這個檔案區塊才會正式被宣告為未使用。
以下我們直接舉一個實際的例子來示範其特性,我們先建立一個一般檔案 a.txt 然後再使用 mklink 工具 ( 註: Windows Vista 以上才有此指令 ) 建立硬式連結,建立完之後無論從 DOS 模式下或檔案總管都看不出這兩個檔案有何差異:
有趣的是,當你修改了 a.txt 的內容,其 b.txt 的內容與修改時間會跟 a.txt 完全一模一樣,但兩者的更新時間會差異個幾秒鐘,不過這並不重要,重要的是兩個檔案不管怎樣都會存取到相同檔案內容。
更好玩的是,不管你建立幾份硬式連結磁碟總使用空間都不會變多,但使用檔案總管統計檔案大小時,卻每一份都會給他算進去,因此建立了硬式連結後,磁碟的使用量統計就會有一些失真,這點是必須特別注意的地方。
如果你今天使用的是 Windows Vista 以前的作業系統,例如 Windows Server 2003 或 Windows XP 之類的,要建立硬式連結就必須靠 Fsutil hardlink 命令來建立,如下圖示:
軟式連結 ( Soft links )
軟式連結最大的優點就是其連結能夠跨磁碟機建立連結,所以比硬式連結還來的彈性許多,這種連結在 Windows 2000 / XP 以前,只有一種稱為 Junction point 類型,這種類型我在幾年前曾經寫過一篇【介紹好用工具:Junction ( Windows 版的 Soft link ) 】文章,就是用來介紹如何利用 Junction 工具來建立目錄的 Soft Links,其使用時的注意事項也請參考該篇文章的內容。
從 Windows Vista 開始,Windows 開始支援另一種 符號連結 (Symbolic Link 或 SYMLINK) 的軟式連結,這種連結又比 Junction point 更加來的彈性許多,除了可以建立目錄的 Soft Link 之外,還能建立檔案的 Soft Link,不但能跨越磁碟機,甚至於還能跨伺服器的建立 Soft Link,非常具有彈性!
以 symbolic link (SYMLINK) 連結來說,在檔案系統中所記錄的是「參照檔案的路徑或檔名」,所以跟硬式連結最大的差異就在於,就算「參照檔案的路徑或檔名」不存在,還是能建立 符號連結。如下圖示,我們試圖建立一個 b.txt 的符號連結,並參考到 a.txt,即便 a.txt 檔案不存在還是能建立符號連結:
這時你從檔案總管可以看出「符號連結」會有不同的圖示,若試圖開啟檔案他會嘗試去解析符號連結所記錄的路徑(相對路徑或絕對路徑皆可),如果找不到檔案就會回報錯誤:
---
瞭解這兩種不同的 NTFS reparse point 之後,最重要的還是要能解決實務上的開發問題,我希望在我們的測試機上不要有太多重複的測試檔案,我們有個目錄下有 8 萬多個檔案,合計將近 3GB,我打算這兩個站台的這些檔案只保留一份就好,另一個站台的目錄就直接用符號連結的方式建立。
比較簡單的作法,我們可以建立「目錄符號連結」最簡單,一個指令就能完成,但在使用 mklink 時要記得加上 /D 參數才行,如下指令與圖示:
mklink /D Temp_Symlink Temp
但我們的另個站台可能會上傳不同的測試資料上去,所以必須用獨立的目錄來儲存這些檔案,因此我們必須大量的建立檔案符號連結才行。
為此我寫了一個好用的批次檔來解決這個問題。以下是批次檔的內容,使用前記得先修改 SourceDir 與 TargetDir 參數,改好之後用滑鼠點兩下即可執行完畢:
@ECHO OFF
:: 請設定來源目錄路徑
SET SourceDir=C:\Inetpub\wwwroot\Content\pictures
:: 請設定要建立【符號連結】的目錄路徑 (所有符號連結的檔案都匯放在這個目錄下)
SET TargetDir=D:\WebTest1\Content\pictures
IF NOT EXIST %SourceDir% (
ECHO.
ECHO 查無來源目錄: %SourceDir%
ECHO.
GOTO End
)
IF NOT EXIST %TargetDir% (
ECHO.
ECHO 查無目標目錄: %TargetDir%
ECHO.
GOTO End
)
:: 本批次檔必須放在 TargetDir 目錄執行
CD /D %TargetDir%
:: 取得來源目錄的所有檔案並取得檔案名稱
for /F %%F in ('dir /B %SourceDir%') do (
:: 若檔案已存在目標路徑則自動跳過建立符號連結
IF NOT EXIST %%F (
mklink %%F %SourceDir%\%%F
)
)
:End
pause
以下是執行時的畫面:
執行完後就會將所有來自於「來源目錄」下的所有檔案全部透過符號連結的方式建立到「目標目錄」下,非常之實用! ^_^
相關連結