问题描述
我使用的是Ubuntu 12.04,我是一个非常新的Linux世界。当我尝试为任何目录创建硬链接并失败时,我感到非常惊讶。我可以为文件系统边界内的文件创建硬链接。我知道我们无法为文件系统以外的文件创建硬连接的原因。
我试过这些命令:
$ ln /Some/Direcoty /home/nischay/Hard-Directory
hard link not allowed for directory
$ sudo ln /Some/Direcoty /home/nischay/Hard-Directory
[sudo] password for nischay:
hard link not allowed for directory
我只想知道背后的原因。对于所有的GNU /Linux发行版和Unix版本(BSD,Solaris,HP-UX,IBM AIX),还是仅在Ubuntu或Linux中都一样。
最佳解决方案
“你一般不应该使用硬链接”是over-broad。您需要了解硬链接和符号链接之间的区别,并根据需要使用它们。每种产品都有其自身的优点和缺点:
符号链接可以:
-
指向目录
-
指向non-existent对象
-
指向同一文件系统之外的文件和目录
硬链接可以:
-
保持它们引用的文件被删除
硬链接在执行“写入时复制”应用程序时特别有用。它们允许您保留目录结构的备份副本,同时仅为两个版本之间的文件使用空间。
命令cp -al
在这方面特别有用。它制作了目录结构的完整副本,其中所有文件都通过硬链接指向原始文件。然后,您可以继续更新结构中的文件,只有您更新的文件才会占用额外的空间。这在维护多代备份时特别有用。
次佳解决方案
目录硬链接以多种方式破坏文件系统
它们允许你创建循环
到目录的硬链接可以链接到它自己的父目录,从而创建文件系统循环。例如,这些命令可以通过反向链接l
创建一个循环:
mkdir -p /tmp/a/b
cd /tmp/a/b
ln -d /tmp/a l
具有目录循环的文件系统具有无限深度:
cd /tmp/a/b/l/b/l/b/l/b/l/b
任何没有-maxdepth
谓词的find
命令都将运行到无限循环。这意味着您不能再以一致的方式使用find
,这是一项重要的命令。类似于同样重要的locate
命令。
根据定义,树没有循环,因此文件系统不再是树。
它们打破了父目录的无歧义性
在文件系统循环中,存在多个父目录:
cd /tmp/a/b
cd /tmp/a/b/l/b
在第一种情况下,/tmp/a
是/tmp/a/b
的父目录。在第二种情况下,/tmp/a/b/l
是/tmp/a/b/l/b
的父目录,与/tmp/a/b
相同。所以它有两个父目录。
他们增加文件
解析符号链接后,文件由路径标识。所以
/tmp/a/b/foo.txt
/tmp/a/b/l/b/foo.txt
是不同的文件。该文件有更多的路径。当然,它们的inode数量相同。但是如果你没有明确地期望循环,那么没有理由去检查这个循环。
一个硬链接目录也可以指向一个子目录,或者一个不是任何深度的父子目录。在这种情况下,作为链接子项的文件将被复制到由两个路径标识的两个文件。
你的榜样
$ ln /Some/Direcoty /home/nischay/Hard-Directory
$ echo foo > /home/nischay/Hard-Directory/foobar.txt
$ diff -s /Some/Direcoty/foobar.txt /home/nischay/Hard-Directory/foobar.txt
$ echo bar >> /Some/Direcoty/foobar.txt
$ diff -s /Some/Direcoty/foobar.txt /home/nischay/Hard-Directory/foobar.txt
$ cat /Some/Direcoty/foobar.txt
foo
bar
那么目录的软链接如何工作呢?
可能包含软链接和甚至软链接目录循环的路径通常用于识别和打开文件。它可以用作正常的线性路径。
但是还有其他一些情况,当使用路径来比较文件时。在这种情况下,可以先解析路径中的符号链接,然后将其转换为最小的,并且通常一致的表示形式,从而创建规范路径:
这是可能的,因为软链接都可以扩展为没有链接的路径。在完成路径中的所有软链接之后,剩余路径是树的一部分,其中路径始终是明确的。
命令readlink
可以解析其规范路径的路径:
$ readlink -f /some/symlinked/path
软链接与文件系统使用的不同
软链接不会造成所有麻烦,因为它与文件系统内的链接不同。它可以与硬链接区分开来,并根据需要解析为没有符号链接的路径。从某种意义上讲,添加符号链接不会改变基本的文件系统结构 – 它保留它,但增加了更多的结构,如应用程序层。
来自man readlink
:
NAME
readlink - print resolved symbolic links or canonical
file names
SYNOPSIS
readlink [OPTION]... FILE...
DESCRIPTION
Print value of a symbolic link or canonical file name
-f, --canonicalize
canonicalize by following every symlink in
every component of the given name recursively;
all but the last component must exist
[ ... ]
第三种解决方案
仅供参考,您可以使用mount实现与目录的硬链接相同的功能:
mount -t bind /var/www /home/user/workspace/www
这是非常危险的,因为大多数工具和程序都不会意识到绑定。我曾经做过类似上面的例子,然后进入rm -rf /home/user
。幸运的是,/var/www
没有任何关联。
第四种方案
不允许hard-linking目录的原因是一个小技术。基本上,they break the file-system structure。无论如何,你通常不应该使用硬链接。符号链接允许大部分相同的功能而不会导致问题(例如ln -s target link
)。