1.简介
操作机某软件异常,进行重装时。对软链接理解存在偏差导致误删除目录问题详细参考 2.3.5 删除目录的软链。
因为未移除感觉软链接,导致安装失败;
尝试删除软链接
/root/bin -> /bin。执行命令
rm /root/bin/时,报错Is a directory。想当然的执行
rm -rf /root/bin/导致将其link的目录/bin删除。目录软链接的删除,应为
rm /root/bin,而非rm -rf /root/bin/。
本文详细记录由链接引伸出来的一系列概念。
2.说明
2.0 基础知识
inode的相关说明:注1
- 跨文件系统(磁盘分区),inode不唯一;
- 每个文件都会占用一个 inode ,文件内容由 inode 来指向blok获取;
- inode与文件名为一对多关系;
系统内部读取文件步骤:注1
- 系统找到
文件名对应的inode - 通过
inode号码,获取inode信息 - 根据
inode信息,找到文件数据所在的block,读出数据。
链接: UNIX文件系统提供的一种将不同文件链接至同一个文件的机制;实际上是一种文件共享的方式,是 POSIX 中的概念,主流文件系统都支持链接文件。
查看文件信息的命令
ls命令
示例:
1 2 3 4hex@hex-PC:/tmp/ln-test$ ls -li total 4 60822147 -rw-rw-r-- 1 hex hex 12 Oct 25 17:36 test 60822175 lrwxrwxrwx 1 hex hex 4 Oct 25 17:36 test-sl -> test参数:
-i查看inode
输出:
- 第一列:inode号
- 第二列:文件权限
- 第三列:链接数目,指一共多少个文件名指向这个inode
- 第四列:文件拥有者
- 第五列:文件所属group
- 第六列:文件大小
- 第七列:文件内容上一次变动的时间
- 第八列:文件名
stat命令
示例:
1 2 3 4 5 6 7 8 9hex@hex-PC:/tmp/ln-test$ stat test-sl File: test-sl -> test Size: 4 Blocks: 0 IO Block: 4096 symbolic link Device: 10302h/66306d Inode: 60822175 Links: 1 Access: (0777/lrwxrwxrwx) Uid: ( 1000/ hex) Gid: ( 1000/ hex) Access: 2022-10-25 17:36:18.216885854 +0800 Modify: 2022-10-25 17:36:16.184873570 +0800 Change: 2022-10-25 17:36:16.184873570 +0800 Birth: 2022-10-25 17:36:16.184873570 +0800参数: 无
输出:
File:显示文件名
Size:显示文件大小
Blocks:文件使用的数据块总数
IO Block:IO块大小
symbolic link:文件类型(软链接)
Inode:inode 号
Links:链接数,即有多少文件名指向这个 inode
Uid:文件拥有者的 Uid
Gid:文件所属group的 Gid
Access:文件的读、写、执行权限
文件的时间戳,共有三个:
- Change:简写为ctime,文件状态(链接数、大小、权限、Blocks数)改变时间。
- Modify:简写为mtime,文件内容的修改时间,文件内容被修改时更新。
- Access:简写为atime,文件内容的访问时间。文件内容被访问时更新。
- Birth: 文件创建时间。
2.1 软链接、硬链接区别
| 功能项 | 软链接 | 硬链接 |
|---|---|---|
| 使用对象 | 文件、目录 | 文件 |
| inode是否相同 | 不同 | 相同 |
| 是否跨文件系统(磁盘分区) | 是 | 否 |
| 原文件删除 | 软链接不可用 | 不受影响 |
| 与原文件的关联项 | 执行命令时,原文件名参数 | 原文件inode |
| 原文件是否必须存在 | 否 | 是 |
| 执行命令 | ln -s <src> <file-sl> | ln <src> <file-hl> |
2.2 软链接
软链接只是一个符号链接,其实就是新建立一个文件,这个文件就是专门用来指向别的文件。大小很小,权限是777,而真正的信息是由指向的原文件决定;
- 删除软链接文件,不影响原文件;
- 删除原文件,则相应的软链接不可用(cat那个软链接文件,则提示“没有该文件或目录“);
2.3 硬链接
硬链接实际上是为文件建一个别名,指向同一个inode。
- 创建硬链接时,不会建立inode,只是在原文件的
inode link count域再增加1; - 删除硬链接时,在原文件的
inode link count域再减1;
系统调用会检查inode link count的数值,如果>=1,那么inode不会被回收,文件的内容不会被删除。
2.4 引申问题
2.4.1 软链接跳转靠的是文件名而非inode
验证思路:设置软链接时,原文件参数传递为相对路径;再将软链接移动到其他目录下;如果报错
Not Found则说明成立软链接查找使用的文件名,为
ln执行命令时传入的原文件,如果是相对路径,则根据软链接路径进行查找。
准备测试环境
1 2 3 4 5# 创建测试目录 mkdir /tmp/ln-test/ cd /tmp/ln-test/ # 生成测试 原文件 echo "source file" > test设置软链接
1ln -s test test-sl查看文件状态
执行命令
ls -li(i参数为查看文件inode)1 2 3 4hex@hex-PC:/tmp/ln-test$ ls -li total 4 60822147 -rw-rw-r-- 1 hex hex 12 Oct 25 17:36 test 60822175 lrwxrwxrwx 1 hex hex 4 Oct 25 17:36 test-sl -> test执行命令
stat <filename>1 2 3 4 5 6 7 8 9hex@hex-PC:/tmp/ln-test$ stat test-sl File: test-sl -> test Size: 4 Blocks: 0 IO Block: 4096 symbolic link Device: 10302h/66306d Inode: 60822175 Links: 1 Access: (0777/lrwxrwxrwx) Uid: ( 1000/ hex) Gid: ( 1000/ hex) Access: 2022-10-25 17:36:18.216885854 +0800 Modify: 2022-10-25 17:36:16.184873570 +0800 Change: 2022-10-25 17:36:16.184873570 +0800 Birth: 2022-10-25 17:36:16.184873570 +0800移动软链接至其他目录
1mv test-sl ../通过软链接
cat文件内容stat 查看软链接属性,
File: test-sl -> test显示软链接指向当前目录test文件,但test文件不存在。1 2 3 4 5 6 7 8 9 10 11 12hex@hex-PC:/tmp/ln-test$ cd ../ hex@hex-PC:/tmp$ stat test-sl File: test-sl -> test Size: 4 Blocks: 0 IO Block: 4096 symbolic link Device: 10302h/66306d Inode: 60822175 Links: 1 Access: (0777/lrwxrwxrwx) Uid: ( 1000/ hex) Gid: ( 1000/ hex) Access: 2022-10-25 17:40:57.608602008 +0800 Modify: 2022-10-25 17:36:16.184873570 +0800 Change: 2022-10-25 17:40:34.131967367 +0800 Birth: 2022-10-25 17:36:16.184873570 +0800 hex@hex-PC:/tmp$ cat test-sl cat: test-sl: No such file or directory软链接所在新目录创建新的
test文件,再查看1 2 3 4 5 6hex@hex-PC:/tmp$ echo "Other test file" > test hex@hex-PC:/tmp$ ls -li test* 60822202 -rw-rw-r-- 1 hex hex 16 Oct 25 17:47 test 60822175 lrwxrwxrwx 1 hex hex 4 Oct 25 17:36 test-sl -> test hex@hex-PC:/tmp$ cat test-sl Other test file
软链接移动前后,inode为60822175,未改变;但前后的原文件test的inode已发生改变60822147 -> 60822202。说明软链接是通过File: test-sl -> test记录所跳转的原文件,而非inode。
2.4.2 硬链接无法跨分区,而软链接可以的原因
硬盘格式化的时候,操作系统自动将硬盘分为两个区域:
数据区:存放文件内容
inode 区:存放 inode 包含的信息,也叫作 inode table
硬链接通过与原文件共用同一inode访问blok读取文件内容。跨分区无法共享inode,所以硬链接无法跨分区。
软链接记录的是原文件的文件名, 而非inode。可以跨分区。
2.4.3 硬链接不支持目录的原因
系统限制对目录进行硬链接只是一个硬性规定,并不是逻辑上不允许、技术上不可行。
其实使用
ln -d命令也允许 root 用户尝试建立目录硬链接,且.与..都是目录的硬链接。
由于 Linux 操作系统中的目录是以
/为节点的树状结构,对目录的硬链接有可能破坏这种结构,甚至形成循环如:/usr/bin -> /usr/,在使用遍历目录的命令时(如:ls -R)系统就会陷入无限循环中。如果使用 hard link 链接到目录时, 链接的数据需要连同被链接目录下面的所有数据都创建链接。因此造成环境相当大的复杂度。
举例来说,如果要将
/etc使用实体链接创建一个/etc_hd的目录时,那么在/etc_hd下面的所有文件名同时都与/etc下面的文件名要创建 hard link 的,而不是仅链接到/etc_hd与/etc而已。 并且,未来如果需要在/etc_hd下面创建新文件时,连带的,/etc下面的数据又得要创建一次hard link。
2.3.4 .与..是目录的硬链接,特殊在哪里
创建目录时,默认会生成两个目录项: . 和 .. 。
.相当于当前目录的硬链接;..相当于父目录的硬链接。
目录硬链接总数:
- 空目录的硬链接总数,等于2(
.和<file-name>); - 目录的硬链接总数,等于 2 + 它的子目录总数(子目录的
..);
2.3.5 目录软链接删除,注意区分 软链接/ 与 软链接
目录的软链接=文件,而非目录文件;例如
目录文件:
/tmp/ln-test/test-dir等同于/tmp/ln-test/test-dir/目录的软链接:
/tmp/ln-test/test-dir-sl<不等于>/tmp/ln-test/test-dir-sl/ rm 前者 == 删除软链接; rm后者 == 删除原目录。
验证:
准备环境
1 2 3 4# 创建目录 mkdir -p /tmp/ln-test/test-dir cd /tmp/ln-test/test-dir设置软链接
1ln -s test-dir/ test-dir-sl查看文件状态
1 2 3 4hex@hex-PC:/tmp/ln-test$ ls -li total 4 60822338 drwxrwxr-x 2 hex hex 4096 Oct 26 10:22 test-dir 60822339 lrwxrwxrwx 1 hex hex 9 Oct 26 10:23 test-dir-sl -> test-dir/软链接stat1 2 3 4 5 6 7 8 9hex@hex-PC:/tmp/ln-test$ stat test-dir-sl File: test-dir-sl -> test-dir/ Size: 9 Blocks: 0 IO Block: 4096 symbolic link Device: 10302h/66306d Inode: 60822339 Links: 1 Access: (0777/lrwxrwxrwx) Uid: ( 1000/ hex) Gid: ( 1000/ hex) Access: 2022-10-26 10:23:12.046192861 +0800 Modify: 2022-10-26 10:23:06.810155908 +0800 Change: 2022-10-26 10:23:06.810155908 +0800 Birth: 2022-10-26 10:23:06.810155908 +0800软链接/的stat1 2 3 4 5 6 7 8 9hex@hex-PC:/tmp/ln-test$ stat test-dir-sl/ File: test-dir-sl/ Size: 4096 Blocks: 8 IO Block: 4096 directory Device: 10302h/66306d Inode: 60822338 Links: 2 Access: (0775/drwxrwxr-x) Uid: ( 1000/ hex) Gid: ( 1000/ hex) Access: 2022-10-26 10:23:12.046192861 +0800 Modify: 2022-10-26 10:22:18.821817214 +0800 Change: 2022-10-26 10:22:18.821817214 +0800 Birth: 2022-10-26 10:22:18.821817214 +0800可尝试执行
stat test-dir和stat test-dir/,会发现与stat test-dir-sl/的inode一致。测试删除
通过上一步stat查看
软链接/和软链接已足够说明问题,通过删除再二次验证删除
软链接/1 2hex@hex-PC:/tmp/ln-test$ rm test-dir-sl/ rm: cannot remove 'test-dir-sl/': Is a directory删除
软链接1 2 3 4hex@hex-PC:/tmp/ln-test$ rm test-dir-sl hex@hex-PC:/tmp/ln-test$ ls -li total 4 60822338 drwxrwxr-x 2 hex hex 4096 Oct 26 10:22 test-dir
2.3.6 应用场景
软链接:
灵活切换不同版本的目标程序
在开发的过程中,对于同一个工具软件,可能要安装多个不同的版本,例如:
Python2和Python3。当在终端窗口中输入:
python时,启动的是python2.7版本。如果有一天需要使用
python3.5版本,只需要把软链接python指向python3.5即可。动态库版本管理
场景描述: 想象这样一个情景,一个程序需要使用
foo_1.1文件中的共享资源,由于foo经常改变版本号。每次升级后都得将使用foo_1.1的所有程序更新到foo_1.2文件,那么每次更新foo版本后,都要重复上边的工作。解决方案:创建一个
foo的软链接指向foo_1.2。这时,当一个程序访问foo时,实际上是访问foo_1.2。当升级到foo_1.3时,只需要更新软链接指向。这不仅解决了版本升级问题,而且还允许在系统中保存两个不同的版本,如果foo_1.3有错误,再更新回原来的foo_1.2链接就可以。快捷方式,将目录层次较深的文件链接到一个更易访问的目录中。
硬链接:
- 不同角度对文件进行分类
- 文件多人共享
- 文件备份
3.总结
- 目录的软链接比较特殊,尤其删除时注意区分带与不带的
/的区别。<软链接>/是原目录本身,后<软链接>是软链接文件; - 硬链接无法跨分区是实现机制决定的,无法创建目录的硬链接是硬性规定(
.与..都是目录的硬链接); - 硬链接共用同一
inode,增加硬链接相当于文件inode的新的别名; - 软链接通过创建时的原文件参数查找原文件,而非原文件
inode(原文件参数==绝对路径,软链接可到处移动。否则不可以);
4.参考
[注1]: linux-inode说明
[注2]: “醉卧沙场:计算机专业性文章及回答总索引-存储和文件系统”
[注3]:Linux是如何跨分区寻找inode
[注4]: “鸟哥私房菜-链接ln说明”