暗色模式

Linux 软链接与硬链接:从 inode 原理到 ln 命令

技术教程
2026-08-12
8
0
本文要点
  • 链接的本质是让多个文件名指向同一个 inode(文件真实数据),理解 inode 是理解链接的前提
  • 硬链接:多个目录项共享同一个 inode,删除任何一个,其余仍可正常读取内容
  • 软链接(符号链接):一个指向「目标路径」的独立小文件,目标被删就变成失效链接(broken link)
  • 目录不允许硬链接;硬链接不能跨文件系统;这两个限制软链接都没有
  • ln 默认创建硬链接,加 -s 参数才创建软链接,所有命令均在 Ubuntu 24.04 上真实执行验证

为什么需要链接

日常使用 Linux 时,你可能遇到过这样的场景:程序升级后版本号变了,路径从 app-1.0 变成了 app-2.0,但脚本里写死的调用路径不能天天改;或者同一个配置文件,既想放在仓库里统一管理,又想让 /etc 下某个路径能直接读到它。

「链接(Link)」就是 Linux 给出的答案:让多个名字指向同一个文件,而不复制数据本身。它有两种形式——硬链接(Hard Link)和软链接(Symbolic Link),两者看起来相似,但底层原理和适用场景完全不同。这篇文章从一个核心概念(inode)出发,把两者的区别、用法和坑一次讲清楚。

链接相关的核心命令是 ln,完整参数可参考 ln(1) 手册页

inode:链接背后的那个概念

在文件系统里,一个文件其实由两部分组成:inode数据块

  • inode(索引节点) 存放文件的元信息:文件大小、权限、属主、时间戳,以及数据块的位置指针。
  • 数据块 才是真正存放文件内容的地方。

你用 ls -i 就能看到每个文件的 inode 编号:

$ ls -li
784976 -rw-r--r-- 1 root root   11 Aug 12 08:03 original.txt
784975 drwxr-xr-x 2 root root 4096 Aug 12 08:03 sub

第一列 784976 就是 original.txt 的 inode 编号,它在同一文件系统内唯一。目录项(文件名 + inode 编号的映射)放在目录里,文件内容放在数据块里——这三者通过 inode 串起来。

理解了这一点,链接的概念就很好懂了:

  • 硬链接 = 在目录里新增一个「文件名 → 同一个 inode」的映射,本质是给同一份数据多开一个名字。
  • 软链接 = 新建一个独立的小文件,里面只存一行「目标路径」字符串,访问时由内核去解析这个路径。
inode 的完整定义与细节可参考 inode(7) 手册页

硬链接:同一份数据的多个名字

硬链接的创建命令是 ln <目标文件> <链接名>,注意不带任何参数

实测:创建硬链接

在演示服务器上实测(Ubuntu 24.04,内核 6.8):

硬链接实测:相同 inode 与链接数变化

图中执行了三步操作:

  1. 创建文件 original.txt(内容 hello link,11 字节),此时 ls -li 显示它的 inode 是 784976,链接数为 1
  2. 执行 ln original.txt hardlink.txt 创建硬链接后,再次 ls -lioriginal.txthardlink.txt 的 inode 都是 784976,而且链接数都变成了 2——说明它们指向的是同一份数据。
  3. 尝试 ln sub 给目录建硬链接,直接报错 hard link not allowed for directory,这是后面会讲的关键限制。

验证「指向同一份数据」更直接的命令是 stathardlink.txtoriginal.txt 共享 inode 784976,链接数 2

硬链接的行为特征

  • 删掉原文件,链接依然有效:硬链接不依赖「原文件」这个名称,只要 inode 的链接数不为 0,数据就不会被回收,任何一个名字都能继续读取内容。
  • 所有名字地位平等:没有「主/次」之分,ls -li 里链接数就是指向该 inode 的硬链接总数。
  • 不能对目录建硬链接:内核用目录的硬链接数记录目录结构,允许用户随意硬链接目录会破坏 . / .. 的相对关系。
  • 不能跨文件系统:硬链接只是 inode 编号的别名,而 inode 编号只在单个文件系统内有效。

后面实测「删除源文件」时,你会看到硬链接和软链接在这一点上的显著差异。

软链接:指向路径的快捷方式

软链接(符号链接)通过 ln -s <目标> <链接名> 创建,-s 是符号链接(symbolic)的开关

实测:创建软链接与失效表现

软链接实测:类型、readlink 与删除源文件后的差异

图中做了三组实验:

  1. ln -s original.txt symlink.txtls -lisymlink.txt 的 inode 是 784984和原文件完全不同,权限位是 lrwxrwxrwx(开头 l 表示 link),文件名后还跟着 -> original.txt 指向目标。
  2. stat 显示它的类型是 symbolic link,大小 12 字节——这个「文件」里存的就是目标路径字符串 original.txt(正好 12 个字符)。readlink symlink.txt 则直接读出它指向的路径。
  3. 删除 original.txt 后对比:cat hardlink.txt 依然能输出 hello link(硬链接不受影响);而 cat symlink.txt 报错 No such file or directory——软链接失效了

软链接的行为特征

  • 本质是路径字符串:软链接里存的是目标路径,访问它等于访问「那个路径」,因此目标可以是文件、目录,甚至不存在的路径(暂时允许,访问时才报错)。
  • 目标被删就失效:软链接不持有数据引用,目标文件删除后,软链接文件本身还在(显示为红色/闪动,file 会提示 broken symbolic link),但访问会失败。
  • 可以跨文件系统、可以指向目录:它只关心「路径」,不关心 inode,所以没有硬链接那两条限制。
  • 多一跳解析开销:每次访问都要先解析路径字符串,再定位目标 inode,理论上比硬链接慢一点点(现代磁盘下基本可忽略)。

硬链接与软链接对比

对比项硬链接软链接(符号链接)
本质指向同一 inode 的目录项别名存目标路径的独立小文件
inode与原文件相同独立 inode
创建命令ln 目标 链接名ln -s 目标 链接名
删除原文件链接仍可正常访问链接失效(broken)
目录不允许允许
跨文件系统不允许允许
查看指向ls -i / stat(inode 相同)ls -l->)/ readlink
占用空间仅新增一个目录项额外存一个目标路径文件
常见用途版本无关的数据别名、去重软件版本切换、快捷方式、简化路径

硬链接的三大限制与软链接的对应

上面说的限制,用命令实测一次就能直观看到:

硬链接限制实测:跨文件系统、目录与失效软链接

图中依次验证了三条规则:

  1. 跨文件系统失败/dev/shm 是内存文件系统(tmpfs),与 /tmp 不在同一文件系统上,ln /dev/shm/x.dat cross.txt 报错 Invalid cross-device link(非法跨设备链接)。换成软链接 ln -s 就不会有这个限制。
  2. 目录硬链接失败ln sub 报错 hard link not allowed for directory
  3. 软链接可指向不存在路径ln -s /nonexistent broken.txt 能成功创建,file 识别为 broken symbolic link,此时还没报错,直到真正访问它才会失败。

应用场景与实用技巧

硬链接的典型场景:

  • 日志/备份去重:同一份数据在多个目录各放一个名字,不占额外空间(前提是同一文件系统)。
  • 版本无关的固定路径:比如 nginx 主程序以「文件名 + 版本」部署,再用硬链接固定一个无版本号的入口,升级只改链接、不改脚本。
  • 替代 cp 的快捷复制:想「复制」一份大文件做引用且不复制数据时,硬链接是零成本方案(注意:修改内容会互相影响,因为是同一份数据)。

软链接的典型场景:

  • 软件版本切换/usr/bin/python -> python3.12current -> app-2.0,升级时改一个链接即可,这几乎是软链接最经典的用途。
  • 跨盘/跨目录统一路径:把数据盘上的 ~/data 软链接到某个程序固定的读取路径下。
  • 多路径共享同一目录:多个服务需要访问同一份配置/缓存目录。

实用技巧:

  • ls -l 看是否带 -> 即可识别软链接;readlink <路径> 直接读出它指向哪里。
  • find -type l 可以批量找出目录下的所有软链接(含失效的,可用 find -xtype l 只找 broken 的)。
  • stat -c '%i %h' 查看 inode 与链接数,排障时判断「两个路径是不是同一份数据」最直观。
  • ln -sf 可以强制覆盖已存在的软链接,ln-f 会先删除目标再创建。
  • 相对路径软链接ln -s ../share/app.conf /etc/app.conf 比绝对路径更便于整体搬迁目录。

总结

一句话记住两者的区别:硬链接是「同一个文件的另一个名字」,软链接是「指向某个路径的快捷方式」。硬链接共享 inode、删原文件不影响、但不能跨文件系统也不能指向目录;软链接是独立的路径字符串文件、可以跨文件系统指向任意路径、但目标被删就失效。

日常使用中,跨目录/跨盘/需要指向目录的场景用软链接,同一文件系统内给同一份数据多开名字的场景用硬链接。理解了 inode 这个底层概念,再面对这两个命令就不会混淆了。

更多链接相关的细节可参考 ArchWiki 的 Symbolic link 条目ln(1) 手册页

发表评论

暂无评论,快来抢沙发吧!