链接也分软硬
我们先来介绍一下软链接和硬链接的概念。
软链接,全称是软链接文件,英文叫作 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 系统中的硬链接有两个限制:
- 不能跨越文件系统。
- 不允许普通用户对目录作硬链接。
至于第一个限制,很好理解,而第二个就不那么好理解了。
我们对任何一个目录用 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.
好了,有关 ln 命令的种种知识和示例,就讲到这里了。如果你对-n
选项的作用理解得还不是非常透彻的话,就多看几遍吧,确实挺难理解的,哈哈。
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/21835.html