ln命令_Linux ln命令:創建文件鏈接

ln 是一個很神奇的命令,它可以創建一個文件的影子,也可以通過一個通道進入另一個地方。其實,所有的這些把戲都是通過軟鏈接和硬鏈接來實現的。本文不會花太多篇幅來深入解釋“硬鏈接”和“軟鏈接”兩個概念,而是更側重在 ln 命令本身的功能和使用上。

鏈接也分軟硬

我們先來介紹一下軟鏈接和硬鏈接的概念。

軟鏈接,全稱是軟鏈接文件,英文叫作 symbolic link。這類文件其實非常類似於 Windows 裏的快捷方式,這個軟鏈接文件(假設叫 VA)的內容,其實是另外一個文件(假設叫 B)的路徑和名稱,當打開 A 文件時,實際上系統會根據其內容找到並打開 B 文件。

而硬鏈接,全稱叫作硬鏈接文件,英文名稱是 hard link。這類文件比較特殊,這類文件(假設叫 A)會擁有自己的 inode 節點和名稱,其 inode 會指向文件內容所在的數據塊。與此同時,該文件內容所在的數據塊的引用計數會加 1。當此數據塊的引用計數大於等於 2 時,則表示有多個文件同時指向了這一數據塊。一個文件修改,多個文件都會生效。當刪除其中某個文件時,對另一個文件不會有影響,僅僅是數據塊的引用計數減 1。當引用計數爲 0 時,則系統纔會清除此數據塊。

如果上述內容理解起來非常困難,那麼還請花些時間閱讀一下《UNIX 環境高級編程》的相關章節,要確保理解這部分知識,才更有助於深入掌握 ln 命令。

建立屬於你的第一個硬鏈接

硬盤上已經有了一個文件,叫作 source.txt,我想針對這個文件建一個硬鏈接文件,名字叫作 hardsource.txt:

#我們的原文件
[roc@roclinux ~]$ cat source.txt
Hello!Source!
 
#先通過ls看看文件信息, 注意開頭的"-", 表示這是一個普通文件
[roc@roclinux ~]$ ls -l source.txt
-rw-rw-r-- 1 roc roc 14 3月   1 00:19 source.txt
 
#用ln命令建立硬鏈接
[roc@roclinux ~]$ ln source.txt hardsource.txt
 
#我們通過ls -i查看兩個文件的inode, 發現是完全相同的, 表示它們指向的是同一數據塊
[roc@roclinux ~]$ ls -il source.txt hardsource.txt
2235010 -rw-rw-r-- 2 roc roc 14 3月   1 00:19 hardsource.txt
2235010 -rw-rw-r-- 2 roc roc 14 3月   1 00:19 source.txt


可以看到,我們建立硬鏈接的命令格式是:

$ ln 源文件名稱 硬鏈接文件名稱


首先,用 ln source.txt hardsource.txt 建立了一個 source.txt 文件的硬鏈接文件。然後,用 ls-il 命令查看了文件的信息。其中,-i選項表示列出每個文件的 inode 節點 ID,可以發現 source.txt 和 hardsource.txt 的 inode 號完全一致,都是 2235010,這就說明它們都指向了同一個數據塊。

這就是硬鏈接,屬於我們的第一個硬鏈接文件。

有一點要注意,硬鏈接不允許跨分區來建立,也不允許跨文件系統來建立,即使是同一類型的文件系統也不行,這主要是受限於 inode 指向數據塊的名字空間。所以,記住,硬鏈接只能在同一個分區內建立。

建立屬於你的第一個軟鏈接

建立一個 source.txt 文件的軟鏈接,名字叫作 softsource.txt。

#用ln -s來建立軟鏈接
[roc@roclinux ~]$ ln -s source.txt softsource.txt
 
#查看文件i節點信息
[roc@roclinux ~]$ ls -il source.txt softsource.txt
2235009 lrwxrwxrwx 1 roc roc 10 3月   1 00:24 softsource.txt -> source.txt
2235010 -rw-rw-r-- 2 roc roc 14 3月   1 00:19 source.txt


可以看到,建立軟鏈接也是使用 ln 命令,但是必須加上-s選項,即 --symbolic 選項。建立軟鏈接的命令格式爲:

ln -s 源文件名稱 軟鏈接文件名稱


我們依然使用 ls-il 命令查看,發現軟鏈接文件 softsource.txt 和源文件 source.txt 的 inode 號是不一樣的,這說明它們完全指向兩個不同的數據塊。而且,細心的朋友能夠觀察到軟鏈接文件的權限欄首字符爲 l(L的小寫字母),這也是軟鏈接文件區別於普通文件的地方之一。

如果這個時候,我們刪除了 source.txt 文件,則軟鏈接 softsource.txt 就會變成紅色字體。這表示警告,說明這是一個有問題的文件,無法找到它所標識的目標文件 source.txt 啦。

建立屬於你自己的目錄鏈接

前面的兩個例子都是創建的文件鏈接,那可以創建目錄的鏈接嗎?自從學會了 ln 命令之後,就像手裏有了一把錘子,總覺得哪兒都是釘子。

[roc@roclinux ~]$ ls -F
tempdir/
 
[roc@roclinux ~]$ ln tempdir linkdir
ln: "tempdir": 不允許針對目錄建立硬鏈接


我想硬鏈接一個目錄 tempdir,但是報錯了!是的,硬鏈接是不允許鏈接到目錄的。至於原因,賣個關子,稍後再揭曉。

我們來嘗試一下針對目錄建立軟鏈接,看看是否可以:

#嘗試建立針對目錄的軟鏈接
[roc@roclinux ~]$ ln -s tempdir/ linkdir
[roc@roclinux ~]$ ls -li
總用量 4
2235009 lrwxrwxrwx 1 roc roc    8 3月   1 00:32 linkdir -> tempdir/
2235011 drwxrwxr-x 2 roc roc 4096 3月   1 00:30 tempdir


成功了,系統允許我們針對目錄建立軟鏈接,看,我建立了一個 tempdir 目錄的軟鏈接 linkdir,以後我完全可以用 cd linkdir 來“進入”temp 目錄了。

#給大家看看tempdir裏的東西
[roc@roclinux ~]$ ls -F tempdir/
linksource.txt
 
#我們通過剛纔創建的軟鏈接, 進入linkdir
[roc@roclinux ~]$ cd linkdir/
 
#看, 就如同進入tempdir一樣
[roc@roclinux linkdir]$ ls -F
linksource.txt

爲什麼 ln 不允許硬鏈接到目錄

Linux 系統中的硬鏈接有兩個限制:

  1. 不能跨越文件系統。
  2. 不允許普通用戶對目錄作硬鏈接。


至於第一個限制,很好理解,而第二個就不那麼好理解了。

我們對任何一個目錄用 ls-l 命令都可以看到其鏈接數至少是 2,這也說明了系統中是存在基於目錄的硬鏈接的,而且命令 ln-d(-d選項表示針對目錄建立硬鏈接)也允許 root 用戶嘗試對目錄作硬鏈接。這些都說明了系統限制對目錄進行硬鏈接只是一個硬性規定,並不是邏輯上不允許或技術上不可行。那麼操作系統爲什麼要進行這個限制呢?

這是因爲,如果引入了對目錄的硬連接就有可能在目錄中引入循環鏈接,那麼在目錄遍歷的時候系統就會陷入無限循環當中。也許有人會說,符號連接不也可以引入循環鏈接嗎,那麼爲什麼不限制目錄的符號連接呢?

原因就在於,在 Linux 系統中,每個文件(目錄也是文件)都對應着一個 inode 結構,其中 inode 數據結構中包含了文件類型(目錄、普通文件、符號連接文件等)的信息,也就是說,操作系統在遍歷目錄時可以判斷出其是否是符號連接。既然可以判斷出它是否是符號連接,當然就可以採取一些措施來防範進入過大過深的循環層次,於是大部分系統會規定在連續遇到 8 個符號連接後就停止遍歷。但是對於硬鏈接,由於操作系統中採用的數據結構和算法限制,目前是不能防範這種死循環的。

基於這樣的考慮,系統不允許普通用戶建立目錄硬鏈接。

ln 命令的 -n 選項有點繞

ln 命令裏面有一個-n選項,它的官方解釋是這樣的:

-n, --no-dereference 
      treat destination that is a symlink to a directory as if it were a normal file.


這個選項理解起來的確有些難度,爲此,我們模擬了一個操作過程,以便讓大家能更好地理解。

第一步:建立兩個文件夾 a 和 b。

[roc@roclinux ~]$ mkdir a b
[roc@roclinux ~]$ ls -F
a/  b/


第二步:針對 a 目錄創建軟鏈接 c。

[roc@roclinux ~]$ ln -s a c
[roc@roclinux ~]$ ls -li
總用量 8
2235012 drwxrwxr-x 2 roc roc 4096 3月   1 00:47 a
2235013 drwxrwxr-x 2 roc roc 4096 3月   1 00:47 b
2235009 lrwxrwxrwx 1 roc roc    1 3月   1 00:48 c -> a


第三步:精髓就在這一步。

#我們再針對b目錄創建軟鏈接c, 造成了軟鏈接c的重複定義
[roc@roclinux ~]$ ln -s b c
 
#軟鏈接c並沒有指向b, 上一條命令似乎並沒有生效
[roc@roclinux ~]$ ls -li
總用量 8
2235012 drwxrwxr-x 2 roc roc 4096 3月   1 00:48 a
2235013 drwxrwxr-x 2 roc roc 4096 3月   1 00:47 b
2235009 lrwxrwxrwx 1 roc roc    1 3月   1 00:48 c -> a
 
#我們進入到軟鏈接c(也就是a目錄)中看一看
[roc@roclinux ~]$ cd c/
 
#竟然發現了一個軟鏈接b指向目錄b, 而且是死鏈
[roc@roclinux c]$ ls -li
總用量 0
2235010 lrwxrwxrwx 1 roc roc 1 3月   1 00:48 b -> b


可以看到,ln 會在 c 軟鏈接目錄(也就是 a 目錄)裏面創建一個 b 的軟鏈接文件,且指向 b 目錄,但很明顯,這不是你的本意。

如果換成 ln-sn b c,那麼結果就變了,我們一起來看。

#加上-n選項後, 系統發現了軟鏈接重複定義的問題, 於是報錯了
[roc@roclinux ~]$ ln -sn b c
ln: 創建符號鏈接 "c": 文件已存在
 
#我們使用-f(--force)來強制建立軟鏈接, 看看效果
[roc@roclinux ~]$ ln -snf b c
 
#看, 原來指向a的符號鏈接c, 現在已經乖乖地指向b了
[roc@roclinux ~]$ ls -li
總用量 8
2235012 drwxrwxr-x 2 roc roc 4096 3月   1 00:51 a
2235013 drwxrwxr-x 2 roc roc 4096 3月   1 00:47 b
2235009 lrwxrwxrwx 1 roc roc    1 3月   1 00:51 c -> b


這就是-n選項的作用,相信通過這樣一個生動的例子,你應該可以理解下面這句話的含義了。

-n, --no-dereference 
      treat destination that is a symlink to a directory as if it were a normal file.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章