ln 软硬链接实战:inode、删除行为与相对路径坑
ln -s 建的软链接,挪个位置就失效;硬链接和软链接的区别,问十个人有八个说不清。这两个问题的根源是同一个概念——inode。把它理解了,ln 的所有行为都变得顺理成章。
这是 Linux 命令系列的一篇,承接 Linux 常见命令与工具地图。ln(link)用来给文件创建链接——同一份内容的另一个访问入口,分硬链接和软链接(符号链接)两种,行为差别很大。
inode:文件名和文件内容是分开存的
文件系统里,一个文件其实是两部分:inode 存文件的实际内容和元数据(大小、权限、时间戳),目录里的文件名只是一个指向 inode 的入口。名字和内容是分离的——这就是理解链接的全部前提。
1 | ls -i a.txt |
stat 那篇 输出里的 Inode 字段、ls -l 的第二列,说的都是这套机制。
硬链接:同一个 inode 的多个名字
1 | ln a.txt b.txt |
因为两个名字完全平等地指向同一份内容,”删除”的语义也变了:
1 | rm a.txt |
这和 lsof 那篇 讲的”rm 掉的文件还占着磁盘”是同一个原理——名字没了不等于内容没了。
硬链接有两个硬性限制:不能跨文件系统(inode 编号只在单个文件系统内有意义,另一块盘上无从指起),不能对目录建(会造成目录树成环)。要跨盘、要链目录,就得用软链接。
软链接:存着路径的独立小文件
1 | ln -s a.txt link.txt |
软链接本质是”存着一个路径的文件”,访问它时系统顺着路径再找真正的目标。所以它没有硬链接的限制——可以跨文件系统、可以指向目录——代价是多了一层间接:目标没了,链接就悬空了:
1 | rm a.txt |
软链接最大的坑:相对路径
软链接里存的路径如果是相对的,它相对的是”链接所在的目录”,不是你执行 ln 命令时所在的目录。这是软链接失效的头号原因:
1 | # 当前目录下有 original.txt,想在子目录 sub/ 里建个链接指向它: |
两种正确写法:
1 | ln -s /full/path/to/original.txt sub/link2.txt |
软链接的两个典型场景
1 | ln -s /opt/app/releases/v2.3.1 /opt/app/current |
硬链接的日常场景少一些,最常见的是备份工具的增量快照——同一份没变过的文件在多个快照目录里用硬链接共享,几十份”全量备份”实际只占一份多的空间。
常用操作速查表
| 命令/概念 | 说明 |
|---|---|
ln 目标 链接名 |
硬链接:同 inode 的另一个名字,语法目标在前 |
ln -s 目标 链接名 |
软链接:存路径的独立文件,可跨盘、可链目录 |
ls -i / ls -l 第二列 |
查看 inode 编号 / 指向该 inode 的链接数 |
| 硬链接删除行为 | rm 只删名字,链接数归零内容才释放 |
| 软链接删除行为 | 删目标后链接悬空;删链接不影响目标 |
| 硬链接限制 | 不能跨文件系统、不能对目录 |
| 软链接相对路径 | 相对于链接所在目录解析,不是执行命令的目录 |
readlink 链接 |
查看链接里存的原始路径,排查悬空第一步 |
ls -l 开头的 l |
权限位首字母 l 即软链接,-> 显示指向 |
写到这里
一句话总结两种链接:硬链接是”同一个 inode 的多个平等名字”,软链接是”存着路径的独立小文件”。删除行为、跨盘限制、悬空问题,全都能从这两句话推出来。日常用得最多的是软链接的版本切换和目录搬迁,记住相对路径那个坑(相对于链接所在目录),基本就不会再踩雷了。










