OFFSET偏移
← 文章目录OFFSET / FIELD NOTESNO. 002

rwx 的另一面。

从 ls 的一整行读起,理解数值权限、目录访问、删除、特殊位与实际排障。

所在专题桌面之下,谁在工作? ↗
约 8 分钟阅读开始阅读

文件是 644,为什么删不掉?目录明明有读权限,为什么进不去?理解权限不能只背 4、2、1,还要看权限作用于文件内容、目录条目,还是访问它们所经过的路径。

先读懂 ls -l 的一整行#

ls -l -- example.txt
ls -lh -- example.txt
ls -ld -- project project/docs

第一条显示长列表,-h 改用便于阅读的大小单位;-d 显示目录自身,而不是把目录里面的条目列出来。判断目录权限时,第三种形式尤其有用。

-rw-r----- 1 alice editors 2048 Oct  8 10:30 example.txt

这是一行虚构示例。依次是类型与模式位、硬链接数、属主、属组、大小、时间与名称。这里 alice 是属主,editors 是属组;并不表示这个文件只可能被两个人使用。目录的大小通常反映目录自身的数据结构,不是把其中所有文件体积相加。硬链接计数也不能在所有文件系统上都直接换算成子目录数量。[1]

标记含义
-普通文件
d目录
l符号链接
b块设备
c字符设备
s套接字
p命名管道(FIFO)

符号链接的显示模式不等于目标文件的实际访问权限。沿链接访问内容时,还要检查目标和通向目标的路径。长列表里出现额外标记时,也要结合工具与平台识别,不能把所有字符都塞进九个模式位里解释。

三组 rwx,八种数字组合#

类型标记后面是三组权限:u 对应属主,g 对应属组,o 对应其他用户。每组依次是读、写、执行;没有相应权限的位置用横线表示。a 在 chmod 的符号表达式中表示三组一起操作。

每组权限用二进制位组合:读是 4,写是 2,执行是 1,相加得到八进制数字。三位数字分别设置 u、g、o,顺序不能换。

数字符号组合
0---无
1--x执行
2-w-写
3-wx写 + 执行
4r--读
5r-x读 + 执行
6rw-读 + 写
7rwx读 + 写 + 执行

因此 755 是属主可读写执行,另外两组可读执行;644 是属主可读写,其余可读;600 则只保留属主读写。下面演示数值设置与符号增减的区别,各行应按实际需要单独选用:

chmod 755 script.sh
chmod 644 notes.txt
chmod 600 private-key.example

chmod u+x script.sh
chmod g-w notes.txt
chmod o-rwx notes.txt
chmod a+r notes.txt

数值写法给出整组普通权限,符号写法适合只调整某一部分。a+r 会给所有三组增加读权限,不是“只给自己读”。修改模式通常要求是属主或具有相应特权;改变属主与属组则由 chown、chgrp 处理,并受各自权限限制。文件归谁、模式是什么,是两个不同问题。

不要把 777 当作通用修复:它会给所有三组开放全部普通权限,却未必能解决只读挂载、ACL、安全模块或路径组件的问题,还可能让本不该修改内容的人获得写权限。

目录上的 x,指的是搜索与穿过#

权限普通文件目录
r读取文件内容读取目录中的名称列表
w修改文件内容修改目录条目;常见操作还需要 x
x作为程序执行的一个必要条件搜索目录,解析目录内路径、穿过它

有目录的 r 而没有 x,可能能列出名称,却无法取得条目的详细信息或访问其中内容;有 x 而没有 r,则可能无法浏览名称列表,但在知道准确名称、并且后续访问也被允许时仍能访问目标。

cd 需要目标目录以及路径前缀具备必要的搜索权限,不要求用 r 先把里面的名字列一遍。反过来,一个文件本身可读,若途中某层目录缺少 x,访问仍会失败。[3]

文件有 x 也不保证能成功执行:格式、解释器路径、挂载选项等仍会影响执行。对脚本而言,./script.sh 与显式让解释器读取 sh script.sh 的访问方式也不同,不能只看一个字符就断言程序一定可运行。

删除一个名称,先看它的父目录#

删除通常是从父目录里移除一个条目,不是先把文件内容逐字擦掉。因此,能写文件内容,不代表能删除它;文件自身没有写权限,也不一定阻止它从一个允许修改的父目录中被移除。

常见的 unlink 操作要求父目录具有写和搜索权限,还要满足 sticky bit 等限制;只读文件系统、不可变属性及额外访问控制也可能拒绝操作。跨目录重命名则要同时考虑涉及的目录,不能只盯住文件那一行 rwx。[4]

改文件内容,看文件;改文件在目录中的名称和位置,看目录;访问它们,还要看整条路径。

s、S、t、T:特殊位与执行位叠在一起#

特殊位借用了执行位的位置显示。SUID 位显示在属主执行位置,SGID 位显示在属组执行位置,sticky bit 显示在其他用户执行位置。小写 s 或 t 表示对应执行位也存在;大写 S 或 T 表示特殊位存在但对应执行位没有设置。不能把所有大写情况都概括成“特殊位无效”。[2]

特殊位典型作用需要分清的边界
SUID对受支持的可执行文件,执行时影响有效用户身份Linux 通常不按普通可执行文件的方式对待解释器脚本上的该位
SGID可执行文件可能影响有效组身份;目录可使新建条目继承目录所属组文件执行语义与目录继承语义不同
sticky bit限制共享目录中的删除、重命名通常只有文件属主、目录属主或具备相应特权者可通过这一限制,其他访问条件仍需满足
-rwsr-xr-x    # 属主 x 位置叠加 SUID
drwxrwxrwt    # 目录上设置 sticky,其他用户仍有 x

这两行只是模式展示,不是建议给任意文件加上相同设置。共享目录里“大家都能创建文件,但不能随意删除别人的文件”,靠的是目录普通权限与 sticky 限制共同作用。

eza 的字符,不要全部按 ls 的外观套#

不同列表工具对类型与扩展信息的显示并不完全一致。eza 的文件类型渲染中,普通文件可用 . 表示,FIFO 用 | 表示;这里的点不是额外增加的一位执行权限。其扩展属性标记 @ 则属于另一类提示。[5]

ls -l -- example.txt
eza -l -- example.txt
eza -l --extended -- example.txt

需要 eza 已安装。用同一文件对照输出,并结合该版本的手册读取扩展属性信息;GNU ls 自己也可能显示额外访问控制的标记,不能据此推导“ls 永远只有十个字符”。颜色、图标与额外列都只是呈现层,最终判断仍要回到文件类型、属主属组和访问控制。[6]

遇到 Permission denied,按路径往里查#

先明确被拒绝的动作是读取、写入、执行、进入目录还是删除。再检查目标及其父目录;路径更深时,逐层确认搜索权限。随后确认当前身份及附加组,判断应落在哪一组模式位上,而不是把三组权限简单相加。

id
ls -ld -- project project/docs
ls -l -- project/docs/example.txt

如果模式位已经允许目标操作,继续检查 ACL、挂载状态、安全策略以及程序实际访问的路径。符号链接指向另一处、程序在容器中运行、检查的文件与报错对象不是同一个,都会造成“权限看着没问题”的错觉。先定位被拒绝的那一步,通常比递归放开整棵目录更快。

参考与延伸

  1. GNU ls 手册 ↗
  2. Linux chmod 与特殊模式位 ↗
  3. Linux 路径解析 ↗
  4. Linux unlink 的权限检查 ↗
  5. eza 文件类型显示实现 ↗
  6. eza 手册与扩展属性 ↗

根据技术笔记重新整理,示例使用通用名称。

沿专题继续阅读

桌面之下,谁在工作?

  1. 01rwx 的另一面。
  2. 02登录之后,谁来接管桌面?
  3. 03从素材到候选窗:一个动态主题的完整链路。
CONTINUE READING / 下一篇登录之后,谁来接管桌面?

从认证、会话条目到环境、自启动与注销,沿着一次登录追踪各层如何交接。