前言
在 Linux 底下的連結檔有兩種,一種是類似 Windows 的快捷方式功能的文件,可以讓你快速的鏈接到目標文件(或目錄),這種是軟鏈接; 另一種則是透過文件系統的 inode 連結來產生新檔名,而不是產生新文件!這種稱為硬鏈接 (hard link)。 這兩種玩意兒是完全不一樣的東西呢!現在就分別來談談。
1. 實體鏈接
在目錄下創建一個條目,記錄着文件名與 inode 編號,這個 inode 就是源文件的 inode。
刪除任意一個條目,文件還是存在,只要引用數量不為 0。
有以下限制:不能跨越文件系統、不能對目錄進行鏈接。
# ln /etc/crontab .
# ll -i /etc/crontab crontab
34474855 -rw-r--r--. 2 root root 451 Jun 10 2014 crontab
34474855 -rw-r--r--. 2 root root 451 Jun 10 2014 /etc/crontab
2. 符號鏈接
符號鏈接文件保存着源文件所在的絕對路徑,在讀取時會定位到源文件上,可以理解為 Windows 的快捷方式。
當源文件被刪除了,鏈接文件就打不開了。
因為記錄的是路徑,所以可以為目錄建立符號鏈接。
# ll -i /etc/crontab /root/crontab2
34474855 -rw-r--r--. 2 root root 451 Jun 10 2014 /etc/crontab
53745909 lrwxrwxrwx. 1 root root 12 Jun 23 22:31 /root/crontab2 -> /etc/crontab
說明
Hard Link (實體鏈接, 硬式連結或實際連結)
在前一小節當中,我們知道幾件重要的信息,包括:
每個文件都會占用一個 inode ,文件內容由 inode 的記錄來指向;
想要讀取該文件,必須要經過目錄記錄的文件名來指向到正確的 inode 號碼才能讀取。
也就是說,其實文件名只與目錄有關,但是文件內容則與 inode 有關。那么想一想, 有沒有可能有多個檔名對應到同一個 inode 號碼呢?有的!那就是 hard link 的由來。 所以簡單的說:hard link 只是在某個目錄下新增一筆檔名鏈接到某 inode 號碼的關連記錄而已。
舉個例子來說,假設我系統有個 /root/crontab 他是 /etc/crontab 的實體鏈接,也就是說這兩個檔名連結到同一個 inode , 自然這兩個文件名的所有相關信息都會一模一樣(除了文件名之外)。實際的情況可以如下所示:
[root@www ~]# ln /etc/crontab . <==創建實體鏈接的命令
[root@www ~]# ll -i /etc/crontab /root/crontab
1912701 -rw-r--r-- 2 root root 255 Jan 6 2007 /etc/crontab
1912701 -rw-r--r-- 2 root root 255 Jan 6 2007 /root/crontab
你可以發現兩個檔名都連結到 1912701 這個 inode 號碼,所以您瞧瞧,是否文件的權限/屬性完全一樣呢? 因為這兩個『檔名』其實是一模一樣的『文件』啦!而且你也會發現第二個字段由原本的 1 變成 2 了! 那個字段稱為『連結』,這個字段的意義為:『有多少個檔名鏈接到這個 inode 號碼』的意思。 如果將讀取到正確數據的方式畫成示意圖,就類似如下畫面:

實體鏈接的文件讀取示意圖
上圖的意思是,你可以透過 1 或 2 的目錄之 inode 指定的 block 找到兩個不同的檔名,而不管使用哪個檔名均可以指到 real 那個 inode 去讀取到最終數據!那這樣有什么好處呢?最大的好處就是『安全』!如同上圖中, 如果你將任何一個『檔名』刪除,其實 inode 與 block 都還是存在的! 此時你可以透過另一個『檔名』來讀取到正確的文件數據喔!此外,不論你使用哪個『檔名』來編輯, 最終的結果都會寫入到相同的 inode 與 block 中,因此均能進行數據的修改哩!
一般來說,使用 hard link 配置鏈接文件時,磁盤的空間與 inode 的數目都不會改變! 我們還是由圖 來看,由圖中可以知道, hard link 只是在某個目錄下的 block 多寫入一個關連數據而已,既不會添加 inode 也不會耗用 block 數量哩!
備注:
hard link 的制作中,其實還是可能會改變系統的 block 的,那就是當你新增這筆數據卻剛好將目錄的 block 填滿時,就可能會新加一個 block 來記錄文件名關連性,而導致磁盤空間的變化!不過,一般 hard link 所用掉的關連數據量很小,所以通常不會改變 inode 與磁盤空間的大小喔!
由上圖其實我們也能夠知道,事實上 hard link 應該僅能在單一文件系統中進行的,應該是不能夠跨文件系統才對! 因為上圖就是在同一個 filesystem 上嘛!所以 hard link 是有限制的:
不能跨 Filesystem;
不能 link 目錄。
不能跨 Filesystem 還好理解,那不能 hard link 到目錄又是怎么回事呢?這是因為如果使用 hard link 鏈接到目錄時, 鏈接的數據需要連同被鏈接目錄底下的所有數據都創建鏈接,舉例來說,如果你要將 /etc 使用實體鏈接創建一個 /etc_hd 的目錄時,那么在 /etc_hd 底下的所有檔名同時都與 /etc 底下的檔名要創建 hard link 的,而不是僅連結到 /etc_hd 與 /etc 而已。 並且,未來如果需要在 /etc_hd 底下創建新文件時,連帶的, /etc 底下的數據又得要創建一次 hard link ,因此造成環境相當大的復雜度。 所以啰,目前 hard link 對於目錄暫時還是不支持的啊!
Symbolic Link (符號鏈接,亦即是快捷方式)
相對於 hard link , Symbolic link 可就好理解多了,基本上, Symbolic link 就是在創建一個獨立的文件,而這個文件會讓數據的讀取指向他 link 的那個文件的檔名!由於只是利用文件來做為指向的動作, 所以,當來源檔被刪除之后,symbolic link 的文件會『開不了』, 會一直說『無法開啟某文件!』。實際上就是找不到原始『檔名』而已啦!
舉例來說,我們先創建一個符號鏈接文件鏈接到 /etc/crontab 去看看:
[root@www ~]# ln -s /etc/crontab crontab2
[root@www ~]# ll -i /etc/crontab /root/crontab2
1912701 -rw-r--r-- 2 root root 255 Jan 6 2007 /etc/crontab
654687 lrwxrwxrwx 1 root root 12 Oct 22 13:58 /root/crontab2 -> /etc/crontab
由上表的結果我們可以知道兩個文件指向不同的 inode 號碼,當然就是兩個獨立的文件存在! 而且連結檔的重要內容就是他會寫上目標文件的『文件名』, 你可以發現為什么上表中連結檔的大小為 12 bytes 呢? 因為箭頭(-->)右邊的檔名『/etc/crontab』總共有 12 個英文,每個英文占用 1 個 byes ,所以文件大小就是 12bytes了!
關於上述的說明,我們以如下圖示來解釋:

符號鏈接的文件讀取示意圖
由 1 號 inode 讀取到連結檔的內容僅有檔名,根據檔名鏈接到正確的目錄去取得目標文件的 inode , 最終就能夠讀取到正確的數據了。你可以發現的是,如果目標文件(/etc/crontab)被刪除了,那么整個環節就會無法繼續進行下去, 所以就會發生無法透過連結檔讀取的問題了!
這里還是得特別留意,這個 Symbolic Link 與 Windows 的快捷方式可以給他划上等號,由 Symbolic link 所創建的文件為一個獨立的新的文件,所以會占用掉 inode 與 block 喔!
由上面的說明來看,似乎 hard link 比較安全,因為即使某一個目錄下的關連數據被殺掉了, 也沒有關系,只要有任何一個目錄下存在着關連數據,那么該文件就不會不見!舉上面的例子來說,我的 /etc/crontab 與 /root/crontab 指向同一個文件,如果我刪除了 /etc/crontab 這個文件,該刪除的動作其實只是將 /etc 目錄下關於 crontab 的關連數據拿掉而已, crontab 所在的 inode 與 block 其實都沒有被變動!
