# 文件权限：rwx 在文件和目录上不是一回事，chmod 两种写法怎么对应

u、g、o 三类对象如何判定，目录的 r、w、x 各管什么，以及 chmod 符号写法与 644、755 这类数字写法的一一对应

> Linux 基础 · 文件系统 · 命令行操作 · 约 8 分钟 · 09 月 23 日

## 本篇要点

1. 权限位分三类对象 u（属主）、g（属组内其他人）、o（其余人），进程只按自己所属的那一类判定，不会挑对自己最有利的一组。
2. 对文件，r 读内容、w 改内容、x 当命令执行；x 不包含 r，所以二进制通常只需 x，而脚本必须同时有 r 和 x。
3. 对目录，r 是能列出名单，w 是能新建/删除/重命名条目，x 是能穿过目录；路径上每一层目录都要有 x，否则里面权限再高也访问不到。
4. 在目录里新建或删除条目都需要同时具备 w 和 search 权限，所以只有 w 没有 x 时 w 落不了地；删除或改名文件取决于所在目录的权限，与文件自己的权限无关。
5. chmod 符号写法格式是 [ugoa][+-=][rwx]，= 会清掉未提到的位；省略 who 时等效于 a，但 umask 里已置上的位不受影响，所以 chmod +x 通常等于给所有人加执行权。
6. chmod 数字写法每位是 4+2+1 的和，三位分别给 u、g、o，它是绝对赋值：644 对应 u=rw,g=r,o=r，755 对应目录或可执行文件。
7. 数字写法最前面还可以有一位控制特殊位：4 setuid、2 setgid、1 sticky；但对目录，数字写法会保留已有的 setuid/setgid 位，要清掉需额外写一位前导零或改用符号写法 g-s。
8. 大写 X 只对目录或本来就有人可执行的文件加 x，是 chmod -R 开放整棵目录树时的正确写法。
9. root 基本绕过这些检查，所以验证权限配得对不对，要换普通用户再试一次。

---

上一篇讲 `cp`、`mv`、`rm` 时，权限已经在旁边冒过好几次头：cp 覆盖一个已存在的文件，目标的属主和权限不会被源文件替换；mv 跨文件系统时这些属性可能根本没带过去；`rm` 删掉一个文件，靠的也不是文件自己的权限。这些现象背后是同一套机制。这篇就把它正面拆开：`ls -l` 里那九个字符到底在说什么，`rwx` 在文件和目录上为什么是两套含义，以及 `chmod` 的符号写法和数字写法如何一一对应。

## 先把 `ls -l` 的第一列读出来

```
$ ls -l /srv/app/deploy.sh
-rwxr-xr-- 1 deploy www-data 2140 Aug 12 09:30 deploy.sh
```

第一列十个字符。第 1 位是类型，常见的是 `-` 普通文件、`d` 目录、`l` 符号链接。后面九位是**三组各三位**的 `rwx`，依次属于：

- `u`，文件的属主（`ls -l` 第三个字段 `deploy` 就是属主）；
- `g`，属组里的其他人（第四个字段 `www-data`）；
- `o`，其余所有人。

所以权限回答的是两个问题：**给谁**（u / g / o），**允许做什么**（r / w / x）。

这里有个容易踩的误区：这三类不是叠加的。进程只按自己所属的那一个类别判定，顺序是属主、属组、其他。所以一个文件权限是 `---r--r--` 时，属主自己反而读不了它，尽管 `o` 那一组写着 `r`。

## 在文件上，r、w、x 大致符合直觉，但有一处要小心

对普通文件：`r` 读内容，`w` 改内容，`x` 把文件当命令执行。

要小心的是 `x` 不包含 `r`。二进制程序通常只有 `x` 就能跑起来，因为内核自己去读这个文件，那不算你的读权限；可脚本不行——内核看到开头的 `#!`，会把文件交给解释器处理，解释器再**以你的身份**打开并读它。所以脚本必须同时有 `r` 和 `x`。`chmod 111 script.sh` 看起来“人人可执行”，实际运行只会得到 `Permission denied`。要跑脚本，用 `755`，或者只给自己用的 `700`。

## 在目录上，rwx 换了一整套含义

这是本篇最需要记住的一节。

- `r`：能读到目录里那张“名单”，也就是 `ls` 能列出名字。
- `w`：能改动这张名单——在里面新建、删除、重命名条目。
- `x`：能穿过它——`cd` 进去，或者按路径访问里面的东西。内核文档里管这个叫 search 权限。

三条推论很实用：

**第一，删掉或改名一个文件，要的是它所在目录的 `w` 和 `x`，跟文件自己的权限无关。** 别人给你一个只读文件，不代表你删不掉它；反过来，你对那个目录没有 `w`，文件给你 `rwx` 也删不了。这就是上一篇说“`rm` 删的是名字不是内容”的另一面：既然删的是目录里的一条记录，要权限的自然就是目录。

**第二，目录的 `x` 在路径上每一层都要有。** `/home/deploy/app/config.yml`，只要 `/home` 或 `/home/deploy` 少了 `x`，哪怕 `config.yml` 是 `777` 你也读不到它。这和第一篇讲路径解析的是同一条规则。

**第三，光有 `w` 没有 `x`，`w` 就落不了地。** 在目录里创建一个条目或者删掉一个条目，都要求同时具备 `w` 和 search 权限。所以 `-w-` 这种权限配出来是空转的。反过来，只有 `r` 没有 `x`（`r--`）时，能列出名字，却看不到每个文件的详细信息（`ls -l` 里那些字段会是问号），也进不去目录。

```mermaid
flowchart LR
  A["想动一个文件"] --> B{"动的是内容还是名字？"}
  B -->|"读、写、执行内容"| C["看文件自己的权限位"]
  B -->|"新建、删除、改名"| D["看它所在目录的 w 和 x"]
  C --> E["路径上每一层目录都要有 x"]
  D --> E
```

顺带解释两个常见的权限值：`/tmp` 是 `1777`，就是“谁都能在里面创建、也能删自己建的东西”，再靠那个 `1`（sticky）挡住别人删你的文件；`/home/you` 通常是 `700`，别人连名字都列不出来。

新文件刚创建时的权限不是随意的：文件基准是 `666`、目录基准是 `777`，再减去你的 umask（通常是 `022`），所以新建文件常常是 `644`、新建目录是 `755`。不加 `-p` 的 `cp` 复制出来的文件，权限也是按你自己这套默认规则生成的，这也是上一篇那个现象的原因。

## chmod 符号写法：描述“要改动什么”

```
chmod u+x deploy.sh      # 属主加执行
chmod g-w,o-r file       # 属组去掉写，其他人去掉读
chmod a=r file           # 三类都只留读
```

格式是 `[ugoa...][+-=][rwx...]`，多段用逗号连起来。`+` 在现有位上增加，`-` 移除，`=` 是“重设成这些”——**没提到的位会被清掉**，所以 `chmod g=r` 会顺手把 g 的 `w` 和 `x` 一起摘掉。

两个细节值得单独记：

省略 `who` 时（比如 `chmod +x`），GNU 的 chmod 把它当作 `a`，但**你的 umask 里已经置上的那些位不受影响**。日常 umask 是 `022`，里面没有 `x` 位，所以 `chmod +x script.sh` 实际上是给属主、属组、其他人全都加了执行权——这比很多人以为的要宽松。

权限字母里还能写大写的 `X`：只对目录、或者本来就已经对某类用户可执行的文件加 `x`。所以“把一整棵目录树开放给同组”的标准写法是 `chmod -R go+rX dir`，它不会把普通的文本文件也标成可执行。

## chmod 数字写法：描述“最终要什么”

每一位是 `r=4`、`w=2`、`x=1` 相加，三位依次给 `u`、`g`、`o`：

| 数字 | 位模式 | 含义 | | 数字 | 位模式 | 含义 |
| --- | --- | --- | --- | --- | --- | --- |
| 0 | `---` | 无权限 | | 4 | `r--` | 只读 |
| 1 | `--x` | 只执行 | | 5 | `r-x` | 读 + 执行 |
| 2 | `-w-` | 只写 | | 6 | `rw-` | 读 + 写 |
| 3 | `-wx` | 写 + 执行 | | 7 | `rwx` | 全权限 |

于是两种写法一一对应：

- `chmod 644 file` = `chmod u=rw,g=r,o=r file`（常见的配置、代码、网页文件）
- `chmod 755 dir` = `chmod u=rwx,g=rx,o=rx dir`（目录、可执行文件）
- `chmod 600 key.pem` = `chmod u=rw,g=,o= key.pem`（私钥、`.env` 这类凭据文件）
- `chmod 2775 shared` = 在 `775` 之上给目录加 setgid，让它里面新建的文件自动归到目录的属组

关键区别在于：**数字写法是绝对赋值**，相当于对三类用户都用 `=`，它完全不看原来的权限是什么。符号写法既可以做加法减法（`+` / `-`），也可以做绝对赋值（`=`）。想改一两个位、又不想影响别处时，用符号写法更安全。

数字写法还能多加一位放在最前面，控制三个“特殊位”：`4` 是 setuid，`2` 是 setgid，`1` 是 sticky。省略的位按前导零理解，所以 `chmod 755` 就是 `chmod 0755`，不会动特殊位。

这里有一个真实的例外要记住：**对目录，GNU chmod 用数字写法时会保留目录上已有的 setuid、setgid 位**，除非你明确写出来。前面那个 `chmod 2775` 设好 setgid 的共享目录，之后有人为了改权限跑一次 `chmod 755`，setgid 不会掉；按文档说明，想用数字写法清掉它需要额外多写一位前导零（如 `00755`），用符号写法 `g-s` 则可以直接清掉。

`ls -l` 里这些特殊位会挤进 `x` 的位置显示：`s`（或 `S`）出现在 `u` 位是 setuid，出现在 `g` 位是 setgid，`t`（或 `T`）出现在 `o` 位是 sticky。大写和小写的区别是那一格有没有 `x`：有 `x` 是小写，没有是大写。

## 几个常见场景和边界

| 场景 | 常见写法 |
| --- | --- |
| 配置、代码、静态文件 | `644` |
| 目录 | `755` |
| 要执行的脚本、二进制 | `755`，只自己用可以 `700` |
| 私钥、凭据文件 | `600`；`~/.ssh` 目录 `700`，里面的 `id_*` 是 `600` |
| 组内协作目录 | `2775`（带 setgid），目录内的文件用 `664` |

最后两条边界：root（更准确地说，具备 `CAP_DAC_OVERRIDE` 的进程）基本绕过这套检查，所以“我这条命令能跑通”不等于“权限配对了”，验证时最好换普通用户身份再试一次。另外，`ls -l` 里类型位是 `l` 的符号链接，它自己的权限位在 Linux 上不生效，实际判定的是它指向的那个文件。

<details>
<summary>动手核对一下</summary>

1. 把 `deploy.sh` 设成“属主可读可写可执行，属组和其他人只能读”，符号写法和数字写法各写一条。
2. 目录 `shared` 现在是 `755`，属组 `members` 里的人需要能在里面新建、删除文件，也能读到里面的文件。目录该怎么设？里面已有的文件还需要处理吗？
3. 一个文件权限是 `-rwxrwxrwx`，`cat` 它却报 `Permission denied`，最有可能是什么原因？

参考答案：1. `chmod u=rwx,g=r,o=r deploy.sh` 或 `chmod 744 deploy.sh`。2. 目录设 `775`（想让它内部新建的文件自动继承属组就设 `2775`）；目录权限只影响“能不能在名单上动名字”和“能不能穿过”，已有文件本身的内容权限是另一回事，`775` 不会顺带放宽它们。3. 路径上某一层目录缺少 `x`，比如 `shared` 被设成了 `644`。
</details>

## 术语表

- 权限类别 u / g / o：同一组权限位复制三份，分别给文件属主、属组内其他人、其余人，进程只按自己所属的那一类判定。
- 目录的 search 权限（x）：决定能不能穿过这个目录、能不能按路径访问里面的条目，路径上每一层都需要它。
- 目录的 w 与删除：新建、删除、改名条目都是在改动目录这张名单，所以只受目录权限约束，与文件自身权限无关。
- umask：决定新文件和新目录默认拿到什么权限（基准 666 / 777 减去它）；chmod 符号模式省略 who 时，也会跳过 umask 里已置上的位。
- 八进制模式：每位由 r=4、w=2、x=1 相加得到，三位依次对应 u、g、o，写出来的效果是绝对赋值。
- 特殊位：数字模式最前面一位的 4（setuid）、2（setgid）、1（sticky）；对目录，GNU chmod 用数字写法时会保留已有的 setuid/setgid。
- X 模式：只对目录、或本来已对某类用户可执行的文件加 x，常用于 -R 递归开放目录树。

## 来源

1. [chmod(1) — Linux manual page：符号模式与八进制模式的定义、省略 who 时 umask 的影响、X 与特殊位、目录 setuid/setgid 的保留与清除写法](https://man7.org/linux/man-pages/man1/chmod.1.html)
2. [ArchWiki: File permissions and attributes — rwx 对文件和目录的对照表，以及只有 w、没有 x 时权限无效等组合效果](https://wiki.archlinux.org/title/File_permissions)
3. [POSIX Base Definitions 第 4 章 — 文件访问权限按所属类别判定与目录保护的描述](https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/basedefs/V1_chap04.html)
4. [execve(2) — Linux manual page：解释器脚本的执行过程与所需的执行 / search 权限](https://man7.org/linux/man-pages/man2/execve.2.html)
5. [Red Hat: Linux file permissions explained — 目录 r / w / x 的实际含义与 sticky 位在 /tmp 上的作用](https://www.redhat.com/en/blog/linux-file-permissions-explained)

---

原文：https://pangzhengboyin.com/articles/linux-file-permissions-rwx-chmod-18f21744

> **庞征博引** · 想学的，慢慢都会
>
> 庞征博引是把想学的东西写成连载的 AI 学习工具。说出想学什么，它会先了解你的基础，再把主题写成一篇篇 5–10 分钟能读完的文章；边读边问，接下来学什么跟着你走。这篇就是这样写出来的。
>
> 开始你自己的连载 → https://pangzhengboyin.com
