一、今日目标
理解 Linux 多用户权限模型,以及文件名、目录项、inode、硬链接和软链接之间的关系,并能把这些知识用于网络服务的配置文件、日志、静态文件和 Unix Domain Socket 排错。
二、权限模型
Linux 访问检查的基本问题是:
text
谁在访问?
访问什么对象?
想执行什么操作?
是否拥有对应权限?
文件权限分为三类主体:
- User:文件所有者。
- Group:文件所属组。
- Others:既不是所有者,也不属于文件所属组的其他用户。
Linux 进程通常具有 UID、GID 和附属组。判断权限时,不能只看用户是否属于某个组,还要看目标文件的具体组权限位。
三、文件权限表示
权限字符:
text
r = read
w = write
x = execute
例如:
text
-rwxr-x---
拆分为:
text
- 普通文件
rwx 所有者:读、写、执行
r-x 所属组:读、执行
--- 其他用户:无权限
数字权限:
text
r = 4
w = 2
x = 1
因此:
text
rwx = 7
rw- = 6
r-x = 5
r-- = 4
--- = 0
-rw-r--r-- 对应 644,表示所有者可读写,组和其他用户只读。
四、普通文件与目录的权限差异
普通文件
r:允许读取文件内容。w:允许修改文件内容。x:允许把文件作为程序执行。
目录
r:允许读取目录项,通常体现为列出目录内容。w:允许创建、删除、重命名目录项。x:允许进入目录或穿过目录访问其中的对象。
关键结论:删除文件主要检查父目录的写权限,而不是只检查文件本身的写权限。读取 /data/config/server.ini 通常需要路径中每一级目录具有穿过权限,并且目标文件具有读权限。
五、inode、目录项和数据块
文件名和文件内容不是直接绑定的。可以抽象为:
text
目录项
├── 文件名
└── inode 编号
↓
inode
├── 类型
├── 权限
├── UID/GID
├── 大小和时间
├── 数据块位置
└── 硬链接计数
目录项可以理解为:
text
文件名 -> inode
inode 保存文件的元数据和数据位置,通常不保存文件名。因此:
text
文件名 != inode
inode != 文件内容本身
六、硬链接
硬链接是多个文件名指向同一个 inode:
text
a.txt ─┐
├── inode 1001 ── 同一份数据
b.txt ─┘
硬链接不是文件复制。两个名字共享同一个 inode、权限和数据。删除其中一个名字后,只要仍有其他硬链接,数据仍然存在。只有链接计数归零,并且没有进程保持该文件打开时,数据才可能被回收。
硬链接通常不能跨文件系统,也通常不允许对目录创建普通硬链接。
七、软链接
软链接是一个特殊文件,保存目标路径:
text
current.conf -> /etc/server/server.conf
软链接拥有自己的 inode,可以跨文件系统,也可以指向目录。目标被删除或路径写错时,软链接会成为悬空链接。访问软链接最终仍要检查目标文件和路径的权限。
八、硬链接与软链接对比
| 特征 | 硬链接 | 软链接 |
|---|---|---|
| 指向对象 | 同一个 inode | 目标路径 |
| 自己是否有独立 inode | 否 | 是 |
| 是否共享数据 | 是 | 通过目标间接访问 |
| 是否通常可跨文件系统 | 否 | 是 |
| 是否通常可指向目录 | 否 | 是 |
| 目标删除后的表现 | 其他链接仍可用 | 可能悬空 |
九、网络服务中的权限场景
配置文件
读取失败可能来自:
- 文件没有读权限。
- 路径中某级目录没有执行权限。
- 软链接目标不存在。
- 服务进程使用的用户不同。
- 启动工作目录不同导致相对路径错误。
日志文件
写入失败可能来自:
- 日志目录没有写权限。
- 文件属于其他用户或组。
- 文件系统只读。
- 磁盘空间不足。
- 服务管理器使用受限用户启动。
HTTP 静态资源
读取 www/index.html 通常需要 www 目录可穿过,且 index.html 可读。
Unix Domain Socket
例如 /tmp/server.sock 是文件系统中的 Socket 路径。排错时还要检查 Socket 文件是否残留、父目录权限以及服务退出后的清理逻辑。
十、权限错误的证据边界
看到 Permission denied 不能立刻断定是目标文件权限问题。还需要区分:
- 路径不存在:
No such file or directory。 - 端口占用:
Address already in use。 - 文件系统只读:
Read-only file system。 - 文件描述符不足:
Too many open files。 - SELinux/AppArmor 等额外策略。
- 手动运行用户与服务管理器运行用户不同。
应收集:错误原文、当前用户、目标路径、路径各级权限、文件所有者/组、启动方式和额外安全策略信息。
十一、理解题标准答案
1. User、Group、Others 分别是什么?
User 是文件所有者;Group 是文件所属组;Others 是既不是所有者也不属于该文件所属组的其他用户。
2. 普通文件的 x 和目录的 x 有什么区别?
普通文件的 x 允许把文件作为程序执行;目录的 x 允许进入目录或穿过目录访问其中的对象。目录的 x 不是"执行目录中的代码"。
3. 为什么删除文件主要检查父目录权限?
删除操作本质上是从父目录中移除"文件名到 inode"的目录项,因此主要需要父目录的写权限和穿过权限。文件本身不可写,不一定阻止删除。
4. 读取路径中的文件为什么目录和文件都要检查?
访问路径需要逐级穿过目录,因此每级目录需要执行权限;最终读取内容还需要目标文件的读权限。
5. inode 是否保存文件名?目录项和 inode 的关系是什么?
通常不保存。目录项保存文件名到 inode 的映射;inode 保存类型、权限、所有者、大小、时间、数据块位置和链接计数等元数据。
6. 硬链接为什么不是复制文件?
硬链接只是增加一个指向同一 inode 的文件名,不会复制数据块,因此多个名字访问同一份数据。
7. 删除一个硬链接后为什么数据可能仍存在?
删除的是一个目录项。只要还有其他硬链接,inode 的链接计数仍大于零,数据仍然有名字可访问。
8. 软链接为什么会悬空?
软链接保存的是目标路径。目标文件被删除、移动或路径写错后,软链接仍存在,但无法沿保存的路径找到目标。
9. 为什么手动启动成功不代表服务管理器启动成功?
两种启动方式可能使用不同用户、组、工作目录、环境变量和安全策略,因此读取配置、写日志或访问 Socket 的权限和路径条件可能不同。
10. Permission denied 应收集哪些证据?
应记录错误原文、当前用户和组、完整目标路径、路径各级目录权限、目标文件权限/所有者/组、进程启动方式、工作目录、文件系统是否只读、磁盘空间以及 SELinux/AppArmor 等策略状态。
十二、验收状态
- 理解 User/Group/Others
- 区分普通文件和目录的
r/w/x - 理解父目录权限对删除和访问的影响
- 理解目录项与 inode 的关系
- 理解硬链接与软链接
- 能列出网络服务权限排错证据
- 用
ls -l、stat、ln、readlink完成最小权限实验
十三、下一步
下一节补做最小权限和链接实验,然后进入 Linux 开发工具:Vim、GCC、编译流程和 Makefile。