首页 > Sysadmin > 正文

Linux 创建软链接与硬链接:ln 实操与常见坑

huyuanwen 2026-10-27 Sysadmin

硬链接是给同一份数据再起一个名字,软链接是存了一条目标路径。ln 的默认行为、两条硬限制、相对路径与换目录链接的坑,均经 WSL 实测。

一、先分清:一个加名字,一个存路径

ln 不带选项建的是硬链接,加 -s 才建符号链接(软链接),这是 GNU 手册的原话;手册把硬链接解释成”已有文件的另一个名字”,和原名不可区分、共享同一个 inode [1]。软链接存的则是一段任意字符串,字符串访问时解析不到文件就成了悬空链接,而且创建悬空的软链接不受任何限制 [1]。差别落到操作上就是这样:

| 属性 | 硬链接 | 软链接 | | — | — | — | | 创建命令 | ln 目标 链接名 | ln -s 目标 链接名 | | 本质 | 同一 inode 的又一个名字 | 存着目标路径的特殊文件 | | 删掉原文件后 | 内容照常可读 | 悬空,立刻打不开 | | 跨文件系统 | 不允许 | 允许 | | 指向目录 | 不允许 | 允许 |

二、建硬链接:用 stat 验证

mkdir -p /tmp/lltest && cd /tmp/lltest
echo data1 > orig.txt
ln orig.txt hard.txt
stat -c "%n inode=%i links=%h" orig.txt hard.txt
echo appended >> hard.txt && cat orig.txt

手册的用法定义:给两个文件名时,ln 把第二个建成指向第一个的链接;建硬链接时目标必须已经存在 [1][2]。实测两个名字的 inode 号相同、links=2;往 hard.txt 追加后 cat orig.txt 两行内容同时出现——两个名字完全对等,没有”原文件”一说。stat 的 %h 是剩余名字数,每删一个硬链接名减一(实测)。

三、建软链接:相对路径按链接自己所在的目录解析

cd /tmp/lltest
ln -s /tmp/lltest/orig.txt abs.txt      # 目标写绝对路径
ln -s orig.txt rel.txt                  # 目标写相对路径
ln -sr /tmp/lltest/note.txt sublink.txt # -r 配合 -s,自动算相对路径
ls -l abs.txt rel.txt sublink.txt
rm orig.txt
cat hard.txt        # 硬链接不受影响
cat rel.txt         # 悬空:No such file or directory,退出码 1
readlink rel.txt    # 仍打出记录的目标路径 orig.txt

两个容易错的点。其一,目标写成相对路径时,解析起点是链接文件所在的目录,不是执行 ln 时所在的目录;把链接挪个位置就可能断,生成时可以用 -r,手册页的说法是”with -s, create links relative to link location” [2]。其二,删掉目标后 cat 报 No such file or directory,但 readlink 照常打出链接里存的路径,排错时先 readlink 再看目标在不在。

四、硬链接的两条硬限制

mkdir d
ln d dhard                                  # hard link not allowed for directory
ln -d d dhard2                              # 即使 root:Operation not permitted
ln /tmp/lltest/note.txt /dev/shm/cross.txt  # Invalid cross-device link
ln -s /tmp/lltest/note.txt /dev/shm/ok.txt  # 软链接跨文件系统:成功

手册口径很明确:硬链接不能跨文件系统边界,且多数系统禁止对目录建硬链接 [1]。实测从 ext4 到 /dev/shm(tmpfs)报 Invalid cross-device link、退出码 1;对目录建硬链接,普通用户报 hard link not allowed for directory,加 -d 以 root 执行也报 Operation not permitted——-d 只是”允许特权用户尝试”,手册页自己注明”即使超级用户也多半会因系统限制失败” [3]。软链接两条都不受限,这是它被广泛用于版本目录切换的原因。

五、换目录软链接的指向:用 ln -sfn

mkdir v1 v2
ln -s /tmp/lltest/v1 dlink
ln -s /tmp/lltest/v2 dlink   # 坑:退出码 0,新链接却落在了 v1 里面
ls -l v1                     # 多出一个指向 v2 的 v2
ln -sfn /tmp/lltest/v2 dlink # 正确姿势:替换 dlink 本身
ls -l dlink

当链接名本身是指向目录的软链接时,ln 默认会把它当目录钻进去,在其指向的目录里新建链接,命令退出码还是 0,属于不报错的那类坑(实测)。-n 的作用就是让这种链接名按普通文件对待,配合 -f 移除旧链接再建新的 [2],所以换指向的标准写法是 -sfn 三连。

六、删除链接、撤销与报错速查

rm 链接名只删链接本身:实测 rm dlink 之后 v1、v2 目录都完好;删掉一个硬链接名,另一个的 links 从 2 变 1、内容完整。改指向就用 ln -sfn 重建,这就是创建类操作的撤销方式。

| 现象 | 原因 | 处理 | | — | — | — | | ln 报 hard link not allowed for directory | 硬链接不能指向目录 | 改用 ln -s | | ln 报 Invalid cross-device link | 硬链接不能跨文件系统 | 用 ln -s,或留在同一文件系统内 | | 加 -d 仍报 Operation not permitted | 内核层拒绝目录硬链接 | 放弃该做法 | | ls 看得到链接、cat 却报 No such file | 目标已删,链接悬空 | readlink 找目标,ln -sfn 指到新目标 | | ln -s 退出码 0 但指向没变 | 新链接建进了目标目录 | 删掉误建文件,用 ln -sfn 重做 |

## 附:实测记录

  • 测试机:WSL2(内核 6.6.114.1-microsoft-standard-WSL2)、Ubuntu 24.04.4 LTS、ln (GNU coreutils) 9.4、ext4 根分区,2026-10-27 以 root 执行,测试文件已清理。
  • inode 与同步:orig.txt 与 hard.txt 同为 inode 41376、links=2;经 hard.txt 写入后 cat orig.txt 两行同现。
  • 悬空表现:rm orig.txt 后 cat hard.txt 正常;cat rel.txt 报 No such file or directory、退出码 1;readlink rel.txt 仍输出 orig.txt。
  • 限制验证:ln 目录报 hard link not allowed for directory;root 加 -d 报 Operation not permitted;ext4 到 /dev/shm(tmpfs)建硬链接报 Invalid cross-device link,ln -s 跨设备成功。
  • 换指向坑:ln -s 指向 v2 的 dlink(dlink 指向 v1)退出码 0,链接落在 v1 内;ln -sfn 后 dlink 指向 v2;rm dlink 不影响 v1、v2;rm 一个硬链接名后 links=1。
  • 未验证:单个文件可建硬链接数的上限;NFS、drvfs 等特殊挂载下硬链接的行为,未在本次环境覆盖。

  • 参考资料

    文中命令已在 WSL Ubuntu 实机执行验证。