我正在使用 Ubuntu 12.04。当我尝试为任何目录创建硬链接时,它失败了。我可以为文件系统边界内的文件创建硬链接。我知道为什么我们不能为文件系统之外的文件创建硬链接。
我尝试了以下命令:
$ ln /Some/Directory /home/nischay/Hard-Directory
hard link not allowed for directory
$ sudo ln /Some/Directory /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 才这样?
答案1
目录硬链接以多种方式破坏文件系统
它们允许你创建循环
目录的硬链接可以链接到其自身的父级,从而创建文件系统循环。例如,以下命令可以使用反向链接创建循环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
遍历这样的目录结构时避免无限循环有点困难(尽管例如 POSIX 要求find
避免这种情况)。
具有这种硬链接的文件系统不再是树,因为根据定义,树不能包含循环。
它们破坏了父目录的明确性
在文件系统循环中,存在多个父目录:
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/Directory /home/nischay/Hard-Directory
$ echo foo > /home/nischay/Hard-Directory/foobar.txt
$ diff -s /Some/Directory/foobar.txt /home/nischay/Hard-Directory/foobar.txt
Files /Some/Directory/foobar.txt and /home/nischay/Hard-Directory/foobar.txt are identical
$ echo bar >> /Some/Directory/foobar.txt
$ diff -s /Some/Directory/foobar.txt /home/nischay/Hard-Directory/foobar.txt
Files /Some/Directory/foobar.txt and /home/nischay/Hard-Directory/foobar.txt are identical
$ cat /Some/Directory/foobar.txt
foo
bar
那么目录的软链接如何工作呢?
包含软链接甚至软链接目录循环的路径通常仅用于识别和打开文件。它可以用作普通的线性路径。
但也有其他情况,即使用路径来比较文件。在这种情况下,可以先解析路径中的符号链接,将其转换为最小并共同商定代表权,创造一个规范路径:
这是可能的,因为软链接都可以扩展到没有链接的路径。对路径中的所有软链接执行此操作后,剩余路径是树的一部分,其中路径始终是明确的。
该命令readlink
可以将路径解析为其规范路径:
$ readlink -f /some/symlinked/path
软链接与文件系统使用的
软链接不会造成所有麻烦,因为它与文件系统内的链接不同。它可以与硬链接区分开来,并在需要时解析为没有符号链接的路径。
从某种意义上说,添加符号链接不会改变基本文件系统结构 - 它保留了它,但增加了更多结构,如应用程序层。
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
[ ... ]
答案2
“无论如何,您通常都不应该使用硬链接”这个说法过于宽泛。您需要了解硬链接和符号链接之间的区别,并酌情使用它们。它们各有优缺点:
符号链接可以:
- 指向目录
- 指向不存在的对象
- 指向同一文件系统之外的文件和目录
硬链接可以:
- 防止他们引用的文件被删除
硬链接在执行“写时复制”应用程序时特别有用。它们允许您保留目录结构的备份副本,同时只使用空间来存储两个版本之间发生变化的文件。请注意,实施时必须先断开链接(否则修改也会应用于原始文件!)。
该命令cp -al
在这方面特别有用。它会完整复制目录结构,其中所有文件都由指向原始文件的硬链接表示。然后,您可以继续更新结构中的文件(在仅创建这些文件的实际副本之后),并且只有您更新的文件才会占用额外空间。这在维护多代备份时特别有用。
答案3
仅供参考,你可以使用 mount 实现与目录硬链接相同的功能:
mount -t bind /var/www /home/user/workspace/www
这是非常危险的,因为大多数工具和程序不会意识到绑定。我曾经做过类似上述示例的事情,然后继续rm -rf /home/user
。幸运的是,中没有任何相关内容/var/www
。
答案4
这不是一个硬链接。
目录本质上是指向父目录的数据块的 inode 的集合、..
目录本身.
(为了子目录/子目录将其作为超级/父目录)、子目录和文件。
硬链接不应该改变 inode 索引的数据块中的数据。
指向目录的硬链接要么需要添加另一个父目录(另一个..
)inode,从而违反上述规则(硬链接不应改变链接到的inode索引的数据块),要么需要导致硬链接目录与原始目录不同(它将具有指向父目录的inode,但从用户的角度来看,该父目录不是明显的父目录)。
澄清
假设你有一个目录 dir-1a ,/
其父目录是它。然后你将其硬链接到一个/
子目录 dir-1b 中,但你没有..
向链接目录添加第二个目录(因为这会更改数据块)。
现在,如果您查看 dir-1b 中的硬链接,它的父目录不是 dir-1b,而是 root。/
这意味着您可以分辨出哪个是硬链接,哪个是原始链接。
硬链接并不是为了与原始链接区分开来。
这种情况会对那些认为硬链接与原始文件不可区分的进程产生连锁反应。目录旨在包含其自身的 inode 以及其硬链接的目录(父目录)。