原力注入

Linux 基础知识 - 软链接 vs. 硬链接

背景知识

Inode 索引节点

要了解硬链接和软链接的区别,首先要明白什么是 Inode。

Inode 是 Index node,索引节点的意思。每个文件都有一个 inode,里边保存着文件的元数据(meta data),包括:inode 号、文件大小、文件所有者、文件权限、文件类型、创建时间、硬链接数等等,除了文件名以外的所有文件信息都存储在这里。它是文件或者目录在一个文件系统中的唯一标识。查看一个文件的 inode,可以用 stat 命令,或者 ls -i 选项来查看。

我们可以看到 xxx-Client.tar.gz 的 Inode 号为:100921812。

stat xxx-Client.tar.gz
  文件:"xxx-Client.tar.gz"
  大小:906908069  块:1771312    IO 块:4096   普通文件
设备:803h/2051d   Inode:100921812   硬链接:1
权限:(0644/-rw-r--r--)  Uid:(    0/    root)   Gid:(    0/    root)
最近访问:2023-09-18 16:57:40.528000000 +0800
最近更改:2023-09-18 16:55:58.671000000 +0800
最近改动:2023-09-18 16:55:58.671000000 +0800
创建时间:-

 ls -i -l xxx-Client.tar.gz
100921812 -rw-r--r-- 1 root root 906908069 9月  18 16:55 xxx-Client.tar.gz

Inode 存储的是文件的元数据(metadata),而与之对应的文件实际内容存储在 数据块(data block)中。因此,文件的内容和属性是分开存储的:

  • • 元数据:存储在 Inode 中,包括文件的大小、权限、所有者等信息。

  • • 用户数据(User Data 或 Data Block):存储文件的实际内容。

文件名、Inode 与数据块的关系

  1. 1. 文件名:是目录中的一项,它指向文件的 Inode。

  2. 2. Inode:记录文件的元数据,并包含指向文件内容所在 数据块 的指针。

  3. 3. 数据块:存储文件的实际内容。

关系图示:

        文件名(Directory Entry)               |               v          Inode(元数据)               |               v      数据块(Data Block,文件内容)

硬链接 - Hard Links

当多个文件名指向同一个 inode 时,这种链接就被称为硬链接。比如像下面的这种情况,我们为原始文件 myfile.txt 创建了两个链接,hardlink1 和 hardlink2,它们都指向同一个 inode,所以它们都是硬链接。从图中可以看出,硬链接指向的文件内容其实就是原始文件的内容,所以硬链接的作用之一就是可以节省磁盘空间。

hardlink1是以目录项(Directory Entry)存储的。在 Linux 文件系统中,目录(Directory)本质上也是一种文件,它的作用是维护一个表格,记录目录中所有文件的文件名和 inode 号之间的对应关系。每一条这样的记录被称为目录项(Directory Entry)。

文件名1:myfile.txt文件名2:hardlink1文件名3:hardlink2      |      v   Inode(元数据)      |      v数据块(Data Block,文件内容)

硬链接的特点

  1. 1. 同一文件系统:硬链接只能在同一个文件系统内创建,不能跨越不同的文件系统或磁盘分区。

  2. 2. 共享 inode:硬链接的文件与原始文件共享相同的 inode,因此它们的内容、权限和属性完全相同。

  3. 3. 节省磁盘空间:多个硬链接共享同一个数据块(文件内容),因此不会占用额外的磁盘空间。

硬链接的另外一个作用就是可以防止文件被“误删”。因为 inode 会记录文件硬链接的次数,只有当硬链接等于 0 的时候,才会把存储着文件内容的数据块删除,所以比如我不小心把 myfile.txt 文件删除了,但是 inode 发现还有另外两个硬链接在,所以不会删除掉数据块,通过两个硬链接我们还是可以读取到文件内容。 

 硬链接可以使用 ln 命令创建,基本格式如下:

ln [选项] [源文件] [链接文件]

注意事项

  1. 1. 硬链接只能对已存在的文件创建,无法对不存在的文件操作。

  2. 2. 硬链接不能跨文件系统,只能在同一文件系统内创建。例如,/home 和 /var 如果属于不同的挂载点,就无法在它们之间创建硬链接。

  3. 3. 硬链接无法对目录创建(除非使用特殊的低级工具,普通用户权限下 ln 不允许对目录操作)。

示例:创建硬链接

ln myfile.txt hardlink1

此命令为 myfile.txt 创建了一个名为 hardlink1 的硬链接,二者共享相同的 inode 和文件内容。

当尝试跨文件系统创建硬链接时,会报错:

ln /home/myfile.txt /mnt/hardlink1

错误信息:

ln: failed to create hard link '/mnt/hardlink1' => '/home/myfile.txt': Invalid cross-device link

这是因为 /home 和 /mnt 属于不同的文件系统,无法创建硬链接。

下面举一个例子来看一下硬链接和源文件的 inode号是否相同,以及删除掉源文件,是否还可以通过硬链接打开原文件。

首先为 xxx-Client.tar.gz 创建两个硬链接 hd1 和 hd2。通过 ls -li 命令查看它们的 inode 号,发现相同,所以验证了我们所说的,硬链接和原文件指向同一个 inode 。另外从长列表中,我们还可以看到 inode 记录的硬链接次数(包括源文件自己),一共是3次。

ls -i -l xxx-Client.tar.gz
100921812 -rw-r--r-- 3 root root 906908069 9月  18 16:55 xxx-Client.tar.gz
ls -li hd1
100921812 -rw-r--r-- 3 root root 906908069 9月  18 16:55 hd1
ls -li hd2
100921812 -rw-r--r-- 3 root root 906908069 9月  18 16:55 hd2

接下来删除掉文件 hd1,通过 ls -li 命令再看一下,发现 inode 记录的链接次数变成了 2,通过硬链接我们还是可以读取原来的文件内容,说明文件内容数据块并没有被删除,只有当硬链接次数变为 0 的时候,文件内容才会真正被删掉。

ls -i -l xxx-Client.tar.gz
100921812 -rw-r--r-- 2 root root 906908069 9月  18 16:55 xxx-Client.tar.gz

硬链接的特点总结

  • • 共享相同的 Inode 和数据块:所有硬链接的文件都指向同一个 inode,因此它们共享相同的文件内容(数据块)。

  • • 删除一个硬链接不会影响其他硬链接:只有当指向同一 inode 的所有硬链接都被删除后,文件的 inode 和数据块才会被真正释放。

  • • 只能对已有文件创建硬链接:无法对不存在的文件创建硬链接。

  • • 不能跨文件系统创建硬链接:硬链接只能在同一文件系统内创建,无法跨不同的挂载点或分区。

  • • 普通用户无法为目录创建硬链接:为避免文件系统结构的混乱,普通用户权限下无法为目录创建硬链接。

软链接 - Soft Links

软链接也被称为符号链接(symbolic link)。Linux 中的软链接和 Windows 的快捷方式非常相似。与硬链接的不同之处在于:

  1. 1. 它的 inode 与原文件不同

  2. 2. 它的数据块存储的是原文件的路径

我们用下面这张图来进行一下说明,我们为 xxx-Client.tar.gz 创建了一个软链接 softlink。可以看出,它的 inode 和 xxx-Client.tar.gz 的 inode 是两个完全不同的索引节点,xxx-Client.tar.gz的数据块记录的是文件的内容,而软链接的数据块记录的是它指向文件的路径。

       文件名:softlink                                文件名:xxx-Client.tar.gz
               |                                                  |
               v                                                  v
        Inode(索引节点)                                 Inode(索引节点)
               |                                                  |
               v                                                  v
  数据块(存储目标文件路径)                       数据块(存储文件内容)
     /path/to/xxx-Client.tar.gz                     [文件的实际数据]

说明:

  • • softlink 是指向 xxx-Client.tar.gz 的软链接文件。

  • • 左侧: softlink 的 inode 独立,数据块中保存的是 目标文件的路径,如 /path/to/xxx-Client.tar.gz。

  • • 右侧: xxx-Client.tar.gz 的 inode 记录了文件的元数据,并指向 文件的实际内容 数据块。

  • • 这也说明了软链接的一个特点:即使原文件位于不同的文件系统,软链接依然能够引用它。

软链接的作用之一也是方便文件的管理,比如原文件的路径比较复杂,我们可以在简单的路径下创建一个软链接,这样比较方便用户访问。但是和硬链接不同的是,一旦原文件被删除,那么软链接就成了一个“死链接”,指向了一个不存在的文件。

在 Linux 中,软链接可以通过以下命令来创建:

ln -s [源文件名或目录] [软链接文件名]

创建软链接的特点:

1. 可以对不存在的文件创建软链接:即使源文件尚未存在,也可以先创建软链接,等文件存在后再使用。例如:

ln -s /path/to/nonexistent/file mylink

当 /path/to/nonexistent/file 创建完成后,mylink 立即生效。

2. 可以跨文件系统:软链接可以跨越不同的文件系统,而硬链接只能在同一文件系统内创建。例如:

ln -s /mnt/external_drive/file.txt ~/file_link

这里的软链接将指向挂载在不同文件系统上的文件。

3. 可以对文件或目录创建软链接:软链接不仅可以指向文件,也可以指向目录。例如:

  • • 指向文件:

ln -s /var/log/syslog ~/syslog_link
  • • 指向目录:

ln -s /var/www/html ~/html_link

举一个例子,比如我们为 xxx-Client.tar.gz 创建一个软链接 softlink。通过ls -li命令查看,发现 inode 号完全不同,并且 myfile.txt 的链接次数还是 1,并没有增加,说明这里的链接次数是指硬链接,通过软链接我们可以读取源文件的内容。

ln -s xxx-Client.tar.gz softlink

ls -i -l xxx-Client.tar.gz
100921812 -rw-r--r-- 1 root root 906908069 9月  18 16:55 xxx-Client.tar.gz

ls -i -l softlink
101367147 lrwxrwxrwx 1 root root 17 10月  4 07:33 softlink -> xxx-Client.tar.gz

删除原文件,软链接变成了“死链接”,通过它再去读取原来的文件内容,系统已经提示文件不存在了。

软链接的特点

  1. 1. 不同的 inode:软链接和其所指向的文件具有不同的 inode 号,并且软链接的数据块存储的是指向文件的路径,而不是文件的内容。

  2. 2. 不增加硬链接次数:创建软链接时,所指向文件的硬链接次数不会增加。软链接本身是一个独立的文件,具有自己的 inode 和数据块。

  3. 3. 删除软链接不影响原文件:删除软链接本身不会对原文件产生任何影响。删除原文件时,软链接会变成“死”链接,指向一个不存在的文件。

  4. 4. 可以指向文件或目录:软链接不仅可以指向文件,也可以指向目录。因此,可以通过软链接访问目录结构。

  5. 5. 可以指向不存在的文件或目录:软链接可以创建指向不存在文件或目录的链接,这种链接通常在目标文件创建后变为有效。

  6. 6. 可以跨文件系统创建:软链接可以跨文件系统创建,不受文件系统边界的限制。这意味着我们可以将软链接从一个文件系统指向另一个文件系统中的文件或目录。

总结

原理上,硬链接和源文件的 inode 节点号相同,两者互为硬链接。软连接和源文件的 inode 节点号不同,进而指向的 block 也不同,软连接 block 中存放了源文件的路径名。实际上,硬链接和源文件是同一份文件,而软连接是独立的文件,类似于快捷方式,存储着源文件的位置信息便于指向。使用限制上,不能对目录创建硬链接,不能对不同文件系统创建硬链接,不能对不存在的文件创建硬链接;可以对目录创建软连接,可以跨文件系统创建软连接,可以对不存在的文件创建软连接。