在什么情况下,您想使用硬链接而不是软链接?我个人从未遇到过要在软链接上使用硬链接的情况,并且在搜索Web时遇到的唯一用例是对相同文件进行重复数据删除。
..
始终与.
父目录中的索引节点相同。诸如此类的操作find
可以检查link-count = 2来检测叶目录,并避免stat
从readdir中查找条目以查找子目录。但这只是对非目录文件的硬链接(常规,符号链接,设备,套接字和命名管道)的支持而启用的次要功能。(是的,符号链接具有自己的inode,并且可以进行硬链接。)
在什么情况下,您想使用硬链接而不是软链接?我个人从未遇到过要在软链接上使用硬链接的情况,并且在搜索Web时遇到的唯一用例是对相同文件进行重复数据删除。
..
始终与.
父目录中的索引节点相同。诸如此类的操作find
可以检查link-count = 2来检测叶目录,并避免stat
从readdir中查找条目以查找子目录。但这只是对非目录文件的硬链接(常规,符号链接,设备,套接字和命名管道)的支持而启用的次要功能。(是的,符号链接具有自己的inode,并且可以进行硬链接。)
Answers:
除了在另一条评论中提到的备份用法(我相信它还包括BTRFS卷上的快照)之外,通过软链接进行硬链接的用例是按标签排序的文件集合。(不一定是创建集合的最佳方法,数据库驱动的方法可能会更好,但是对于一个相当稳定的简单集合来说,还算不错。)
一种媒体收藏,其中所有文件都存储在一个目录中,并根据各种条件(例如,年份,主题,艺术家,流派等)分类到其他目录中。这可以是个人电影收藏,也可以是商业工作室的收藏作品。本质上说,文件被保存,不太可能被修改,并可能通过链接分类到多个位置。
请记住,“原始”和“复制”的概念不适用于硬链接:指向文件的每个链接都是原始链接,正常情况下没有“复制”。但是,对于用例的描述,这些术语模仿行为的逻辑。
“原始”保存在“目录”目录中,排序后的“副本”硬链接到这些文件。可以将排序目录上的文件属性设置为r / o,以防止对文件名和排序结构的任何意外更改,而目录目录上的属性可以是r / w,允许根据需要对其进行修改。(这种情况的例子是音乐文件,其中一些播放器尝试根据用户输入或Internet检索中基于媒体文件中嵌入的标签来重命名和重新组织文件。)此外,由于“复制”目录的属性可能不同于在“原始”目录中,可以对访问权限受限的组或世界提供排序的结构,而主要“目录”只能由主要用户访问,具有完全访问权限。但是,文件本身在指向该索引节点的所有链接上始终具有相同的属性。(可以探索ACL来增强它,但不能增强我的知识领域。)
如果原始文件被重命名或移动(例如,单个“目录”目录变得太大而无法管理),则硬链接仍然有效,软链接断开。如果“副本”被移动并且软链接是相对的,则软链接将再次断开,而硬链接将不会断开。
注意:当涉及软链接时,不同的工具如何报告磁盘使用情况似乎不一致。但是,使用硬链接似乎是一致的。因此,如果将目录中的100个文件分类为“标签”的集合,则很容易就有500个链接的“副本”。(例如,对于一个照片集,例如日期,摄影师,以及平均3个“主题”标签。)例如,海豚会报告为硬链接为100个文件,如果使用软链接为600个文件。有趣的是,它以两种方式报告相同的磁盘空间使用情况,因此对于软链接而言,它看起来像是一大堆小文件,对于硬链接来说,它看起来像一小堆大文件。
这种用例的一个警告是,在使用COW的文件系统中,修改“原始”可能会破坏硬链接,但不会破坏软链接。但是,如果要复制原版,则在编辑,保存和排序后,COW不会进入场景。
stat
只会显示一个链接。
stat
显示相同的索引节点号,但显示不同的设备ID。必须与子卷叠加在很少安装的主卷上的方式有关。我怀疑如果安装了主卷,则stat
链接数量将等于持有该文件版本的快照数量。COW可能会考虑修改一个而不影响其他任何一个。仅仅是基于轻微的好奇心而进行的猜测,但还不足以使人们更深入地了解。
硬链接在您不想同时存在两个文件的情况下很有用。考虑一下:
touch a
ln -s a b
rm a
现在b
没用了。(这些步骤可能相距很远,可以由不同的人来完成,等等。)
而通过硬链接,
touch a
ln a b
rm a
b
仍然存在并且正确。
单个程序可能会更改其行为,具体取决于它以什么名称启动:
$ ls -li `which pgrep` `which pkill`
208330 -r-xr-xr-x 2 root bin 19144 Jul 26 2016 /usr/bin/pgrep
208330 -r-xr-xr-x 2 root bin 19144 Jul 26 2016 /usr/bin/pkill
源中的哪个是通过类似的方式决定的
if (strcmp(__progname, "pgrep") == 0) {
action = grepact;
pgrep = 1;
} else {
action = killact;
尽管确切的细节会随所涉及的操作系统和语言而有所不同。
这允许(大部分)相同的代码不必编译成两个(大部分)相同的二进制文件。请记住,unix可以追溯到磁盘空间非常昂贵的日子,尽管根据Stevens在APUE中的第4章,符号链接是在BSD4.2(1983)中实现的,以替代硬链接的各种限制。用于检查符号链接名称是否用作程序名称的测试程序可能类似于:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
printf("called as '%s'\n", *argv);
exit(0);
}
并通过以下方式进行了测试:
$ cc -o myname myname.c
$ ln -s myname alias
$ ./myname
called as './myname'
$ ./alias
called as './alias'
$
当我的P2P软件完成下载特定文件时,该文件将放置在特定目录中。下载的文件几乎不需要进行编辑。常见的情况是我在需要文件的其他目录中进行了硬链接。
好处:
rm
还是mv
“副本”,我仍然应该在P2P网络中共享文件。rm
“原始”停止共享文件;此操作不会影响所需位置的“复制”。要点:如果我事先知道rm
首先要使用哪个文件,则可以使用symlink。但是我永远不知道。
文件系统是一种简单而有效的组织和分类文件的方法(这是它们存在的最主要原因)。硬链接在此问题上具有更高的灵活性。
如前所述,在处理硬链接时没有原始和副本的概念,所有目录条目(硬链接)只是对文件存在的引用(指向其inode的引用),没有优先权,因此也没有损坏的硬链接。 。
因此,这里有一些硬链接参与但不包含软链接的用例:
假设您拥有电影,音乐或其他媒体的集合,并且希望应用不同的分类标准,例如按艺术家在分支中分类的歌曲(每个艺术家都有自己的子目录);依流派在另一个分支中(每个流派都在不同的子目录中),等等。仍然您不希望复制文件,也不想决定将“原始”文件放置在何处,以便您可以自由地进行重新分类而不必“管理”,并在移动时重新链接文件,以避免链接断开。
另一个原因是避免浪费相同文件的多个副本所需要的存储空间,但又允许chroot
syscall受益于“主”文件系统根目录中的一部分文件(符号链接永远不能从外部引用文件)在chroot
沙箱中,即使他们有相对路径)。
..
子目录是存在硬链接的另一个非常重要但很少被提及的原因。这些..
目录实际上是(在大多数unix fs实现中)到父目录的硬链接,没有硬链接则必须以完全不同的方式来实现,而硬链接的存在使得此实现非常容易。
最近,我有一个用例,用于基于U-Boot的系统的安全性较高的更新过程,其中uImage
是一个指向要引导映像的软链接,其思想是断电不会造成任何问题,无论在何时中断。处理过程(假设文件系统运行):
ln image.bin backup_image.bin
ln -sf backup_image.bin uImage
// replace image.bin
ln -sf image.bin uImage
rm backup_image.bin
没有硬链接就不会那么简单。
/编辑:
由于有了这些评论,我现在知道这样做会更好:
ln image.bin backup_image.bin
ln -sf backup_image.bin uImageNew
mv uImageNew uImage || rm -rf uImage && mv uImageNew uImage
// replace image.bin
ln -sf image.bin uImageNew
mv uImageNew uImage || rm -rf uImage && mv uImageNew uImage
rm backup_image.bin
(rm
这里是为了能够更好地逃脱一个奇怪的状态,例如,如果uImage
某件事出乎意料而会mv
失败[但不一定是先前的ln -sf
解决方案]。)
ln -sf
是不是原子的。它将删除旧的符号链接并创建一个新的符号链接。要解决此问题,您需要创建一个带有临时名称的新符号链接,并将其rename(2)
(mv
)替换为您要替换的符号链接的名称。
stat("uImage", {st_mode=S_IFREG|0777, st_size=0, ...})
unlink("uImage")
,symlink("backup_image.bin", "uImage")
install.sh
解决该问题:git.musl-libc.org/cgit/musl/tree/tools/install.sh
mv
即使使用也会-f
失败。演示:ln -sf foo bar; ln -sf bar foo; echo "Before:"; ls -l foo bar; >testfile; mv testfile foo || { echo "Using mv -f"; mv -f testfile foo; }; echo "After:"; ls -l foo bar
我对硬链接的一种用途是下载或解压缩损坏的文件时。进行下载或解压缩的程序(例如unzip或unrar)在遇到错误时通常会自动删除不完整的文件,通常没有选择保留它。如果要保留该文件,可以对其进行硬链接。
BackupPC是一个备份系统,它使用服务器上的硬链接来提供文件级重复数据删除。
首先根据文件的md5哈希将文件存储在“池”目录树中。任何使用该文件的备份都会硬链接到池文件。随着备份过期/删除,其硬链接将从文件系统中删除。
此处,硬链接优于软链接,因为它们提供了自动引用计数。cron作业会定期删除池目录中没有多个链接的任何文件。
这种方法有一些缺点(主要是很难使用基于文件系统的工具来复制备份存储),但实践证明它非常健壮。
另一个用例:tomcat Java Web应用程序服务器将文件名视为元数据。必须根据Web服务器上的路径命名Java“ war”文件。
例如:foo.war
是提供网址的Java代码/foo
不幸的是,它在做出此决定之前会解决符号链接。
因此,假设您想部署一个应用程序构建,并为其提供一个描述性文件名(例如,带有发行号或日期)。您不能使用“真实”名称对文件进行符号链接-您必须进行硬链接。
foo.war
链接到foo-20170129.war
不起作用
foo.war
硬链接到foo-20170129.war
作品。
我不喜欢这种tomcat行为,但是硬链接为我提供了解决方法。