Linux 权限管理:从「Permission Denied」到「畅行无阻」
如果你曾在终端里敲命令时被一句
Permission denied怼回来过,这篇文章就是为你准备的。我们将从「为什么要有权限」开始,把用户切换、rwx、chmod 八进制、umask 掩码、粘滞位这些看似零散的知识点串成一条完整的逻辑链。
前置知识:为什么会有「权限」这种东西?
一个很现实的场景
Linux 是多用户操作系统。一台服务器上可能同时有 root 管理员、后端开发、前端开发、运维实习生同时登录。如果实习生不小心rm -rf /,那就出大事了。
权限的本质:决定谁(用户/角色)能对什么资源(文件/目录)做什么操作(读/写/执行)。
权限 = 人(用户 + 角色) + 文件属性(rwx)- 人:你的账号身份是什么?root 还是普通用户?你在目标文件面前扮演什么"角色"?
- 文件属性:目标文件身上挂了哪些权限标签(可读?可写?可执行?)
两种用户级别
| 用户类型 | 特点 |
|---|---|
| root(超级用户) | 不受权限限制,可以做任何事。例如 root 切换到任何普通用户都不需要密码 |
| 普通用户 | 受权限约束,只能访问自己被授权的内容 |
🔑 root 的"特权体现"之一:
su切换到任何用户无需输入目标用户的密码,而普通用户su切换时必须输入目标密码。
第一部分:su 和 sudo —— 切换身份的两种姿势
su(switch user)
su # 不跟用户名,默认切换到 root(因为系统 100% 存在 root) su alice # 切换到 alice 用户 su - # 以"重新登录"的方式切换,自动跳转到目标用户的家目录 su - alice # 组合用法密码规则:
| 切换方向 | 需要谁的密码? |
|---|---|
| 普通用户 → root | 输入root密码 |
| root → 普通用户 | 不需要密码(特权) |
| 普通用户 A → 普通用户 B | 输入B的密码 |
sudo(super user do)
su的问题是什么?你告诉了别人 root 密码,他就能为所欲为。sudo解决了这个问题。
sudo vim /etc/nginx/nginx.conf # 临时提权执行单条命令sudo 的逻辑:
- 你输入自己的密码(不是 root 密码!)
- 系统查
/etc/sudoers这个白名单文件,看你是不是被允许执行这条命令 - 白名单的编辑权限只在 root 手里,普通用户改不了
❓为什么 sudo 不设计成输入 root 密码?
如果输入的是 root 密码,那 sudo 就退化成了 su —— 知道 root 密码的人还是可以为所欲为。sudo 的设计哲学是:短暂地放宽一个受信任用户的权限,而不是交出 root 的钥匙。白名单机制让 root 可以在不泄露自己密码的前提下,精准控制"谁可以做什么"。
su vs sudo 对比:
| su | sudo | |
|---|---|---|
| 需要谁的密码 | 目标用户的密码 | 自己的密码 |
| 权限范围 | 完全切换身份 | 单条命令临时提权 |
| 安全程度 | 知道 root 密码 = 拥有 root | 白名单精准控制,root 密码不外泄 |
| 适用场景 | 管理员日常维护 | 给普通用户开放特定高权限操作 |
第二部分:文件权限的构成 —— 三个角色 × 三种操作
用ls -l看一个文件的属性:
-rw-r--r-- 1 alice dev 50 Jul 19 17:23 test.txt拆解第一列的-rw-r--r--:
- rw- r-- r-- │ │ │ │ │ │ │ └── other 权限(其它用户) │ │ └───────── group 权限(所属组) │ └──────────────── user 权限(拥有者) └────────────────────── 文件类型(- = 普通文件,d = 目录,l = 链接)三个角色
| 角色 | 缩写 | 说明 | 举例 |
|---|---|---|---|
| 拥有者 | u(user) | 文件的主人,一般是创建者 | alice 创建的test.txt,拥有者是 alice |
| 所属组 | g(group) | 一个用户组,组内成员共享权限 | dev 组的所有成员对test.txt拥有 g 权限 |
| 其它者 | o(other) | 既不是拥有者、也不属于所属组的所有人 | 路人甲 |
❓为什么要有所属组?
当你想对特定的一群人开放权限,而不是对所有人开放时,组就是最合适的管理单元。比如后端开发组能读写项目代码,但前端组只能读。
三种权限
| 权限 | 字母 | 对文件 | 对目录 |
|---|---|---|---|
| 可读 | r | 能查看文件内容(cat、more) | 能列出目录内的文件名(ls) |
| 可写 | w | 能修改文件内容 | 能在目录内新增、删除、重命名文件 |
| 可执行 | x | 能运行该文件(可执行程序/脚本) | 能进入该目录(cd),能访问目录内文件 |
🔴关键认知:同一个 r/w/x,对文件和目录的含义完全不同。比如目录的 w 权限决定的是你能不能在里面新建/删除文件,而不是修改目录本身的内容。
第三部分:chmod —— 修改文件权限
⚠️ 只有文件的拥有者和root才能修改文件的权限。
方式一:符号法(直观,适合新手)
chmod 角色 操作 权限 文件名 │ │ │ u + r g - w o = x a(all,全部)示例:
chmod u+w test.txt # 给拥有者添加写权限 chmod g-r test.txt # 去掉所属组的读权限 chmod o+x script.sh # 给其它用户添加执行权限 chmod a+r shared.txt # 给所有人添加读权限(等于不写角色,默认 a) chmod u-rw,g+r test.txt # 同时修改多个角色,用逗号隔开(逗号后不要加空格!) chmod u=rwx,g=rx,o= test.txt # = 表示精确设置为指定权限(o= 表示 other 没有任何权限)方式二:八进制数字法(更常用,高手必备)
每个权限对应一个数字:
r(读)= 4 w(写)= 2 x(执行)= 1 -(无)= 0 例如: rwx = 4+2+1 = 7 rw- = 4+2+0 = 6 r-x = 4+0+1 = 5 r-- = 4+0+0 = 4 -w- = 0+2+0 = 2 --x = 0+0+1 = 1 --- = 0+0+0 = 0三个角色各用一个 0~7 的数字表示,组成三位数:
chmod 755 script.sh # rwx r-x r-x → 拥有者全权限,其他人只读+执行 chmod 644 data.txt # rw- r-- r-- → 拥有者可读写,其他人只读 chmod 600 secret.txt # rw- --- --- → 只有拥有者能读写(私密文件) chmod 777 public.txt # rwx rwx rwx → 所有人全权限(不安全!)常见数字组合速查:
| 数字 | 含义 | 典型用途 |
|---|---|---|
755 | rwx r-x r-x | 可执行脚本、目录 |
644 | rw- r-- r-- | 普通文本文件 |
600 | rw- --- --- | 私钥、密码文件 |
700 | rwx --- --- | 个人脚本 |
777 | rwx rwx rwx | 临时共享(⚠️ 不推荐长期使用) |
⚡ 权限匹配的"一次验证"原则
这是一个很容易踩坑的机制:
用户访问文件时,系统按照u → g → o的顺序匹配身份,只匹配一次。一旦身份确定,就只看该身份的权限,不会因为 g 权限更大而"降级"使用。
示例:alice 是test.txt的拥有者,同时也是其所属组dev的成员。
-r---w-rw- 1 alice dev test.txtalice 对此文件的权限是r--(只有读),不是rw-。为什么?因为系统先匹配到她是拥有者(u),就锁定用 u 的权限(r--),不会再去检查她作为组成员的 g 权限。
💡 一句话:权限验证是"一次匹配,立即生效",不是"取所有身份的最大权限"。
第四部分:chown 和 chgrp —— 修改文件的拥有者和所属组
⚠️ 修改拥有者和所属组是root 专属权限。即使你是文件的拥有者,也不能把文件"送给"别人,只能用
sudo。
# chown:修改拥有者(change owner) chown root test.txt # 把拥有者改为 root chown alice:dev test.txt # 同时修改拥有者和所属组 chown :dev test.txt # 只修改所属组(冒号前留空) # chgrp:修改所属组(change group) chgrp dev test.txt # 把所属组改为 dev实际演示:
[root@server ~]# ll -r-------- 1 whb whb 50 Jul 19 17:23 test.txt # 拥有者 whb,所属组 whb [root@server ~]# chown root test.txt -r-------- 1 root whb 50 Jul 19 17:23 test.txt # 拥有者 → root [root@server ~]# chgrp root test.txt -r-------- 1 root root 50 Jul 19 17:23 test.txt # 所属组 → root [root@server ~]# chown whb:whb test.txt -r-------- 1 whb whb 50 Jul 19 17:23 test.txt # 一键改回第五部分:Linux 文件类型速览
ls -l输出的第一个字符代表的不是权限,而是文件类型:
| 首字符 | 类型 | 说明 | 举例 |
|---|---|---|---|
- | 普通文件 | 源代码、文本、可执行程序、图片、库 | hello.c、a.out |
d | 目录 | 目录本质上也是文件,存储的是其内部文件的元数据列表 | my_project/ |
l | 符号链接 | 相当于 Windows 的快捷方式 | /lib64 → usr/lib64 |
c | 字符设备 | 按顺序 IO,以字符为单位,不支持随机读写 | 键盘、显示器 |
b | 块设备 | 支持随机读写,以数据块为单位 | 硬盘、U 盘 |
p | 管道文件 | 进程间通信 | |
s | 套接字 | 网络/本地进程间通信 |
第六部分:目录的 rwx —— 一个容易搞错的地方
目录本身只是一个"登记表",存储的是内部文件的属性(文件名、inode 号等),而不是文件的内容。理解了这一点,下面的规则就顺了。
进入一个目录需要什么权限?
| 权限 | 能否进入目录(cd) | 能否 ls 查看文件名 | 能否在目录内新建/删除/重命名 | 能否访问目录内的文件 |
|---|---|---|---|---|
| 只有 r | ❌ 进不去 | ✅ 能 ls(但看不到详细信息) | ❌ | ❌(进都进不去) |
| 只有 w | ❌ 进不去 | ❌ | ❌(进不去,谈何操作) | ❌ |
| 只有 x | ✅ 能进 | ❌ 无法 ls | ❌ | ✅(知道文件名就能读内容) |
| r + x | ✅ 能进 | ✅ 能 ls | ❌ | ✅ |
| w + x | ✅ 能进 | ❌ | ✅ | ✅(知道文件名就行) |
| r + w + x | ✅ 能进 | ✅ | ✅ | ✅ |
🔑记忆技巧:
- x是"进门卡" —— 没有 x,目录的门你都进不去
- r是"花名册" —— 允许你查阅目录里有哪些文件(
ls)- w是"增删改签" —— 允许你在花名册上添加、划掉、改名(不影响文件内容本身)
一个反直觉的细节
如果目录的 w 权限被关闭,但文件的 w 权限保持打开:
chmod 555 mydir/ # 目录:r-x r-x r-x(没有 w) # 此时无法在 mydir/ 下新建、删除、重命名文件 # 但如果 mydir/ 下已有文件 hello.txt(rw-rw-rw-)... vim mydir/hello.txt # ✅ 可以修改文件内容!目录的权限管不到文件内容 —— 它只管"登记表"上的增删改。所以:
删除文件 ≠ 修改文件内容。删除是修改目录的"登记表"(目录的内容),修改是改文件的"正文"(文件的内容)。两者互不干涉。
第七部分:umask —— 为什么新建文件的默认权限是那样?
新建一个文件/目录时,默认权限是怎么来的?
起始权限
| 文件类型 | 起始权限 | 原因 |
|---|---|---|
| 普通文件 | 666(rw-rw-rw-) | 默认不需要执行权限,大部分文件是文本/数据 |
| 目录 | 777(rwx rwx rwx) | 进入目录需要 x,所以默认给予 |
权限掩码 umask
但实际新建的文件并不会是 666/777。看看你自己系统:
$ umask 0002umask(权限掩码)的作用:凡是在掩码中出现的权限,都要在起始权限中去掉。
最终权限 = 起始权限 & (~umask) # 位运算:取反后按位与⚠️ 这个"去掉"不是数学减法,而是位运算。不要用
777 - 022 = 755来理解,虽然结果碰巧相同,但原理完全不同。
实际计算
假设umask = 022(最常见的值):
普通文件: 起始 666 rw- rw- rw- umask 022 --- -w- -w- (掩码:要去掉组写和其他写) ~umask 755 rwx r-x r-x 666 & 755 = 644 rw- r-- r-- 目录: 起始 777 rwx rwx rwx 777 & 755 = 755 rwx r-x r-x结论:
- 新建普通文件 →
rw- r-- r--(644):拥有者可读写,其他人只读 ✅ - 新建目录 →
rwx r-x r-x(755):拥有者全权限,其他人可读可进入 ✅
💡umask 越大,默认权限越小。例如
umask 077会让新建文件只有拥有者能访问。
修改 umask
umask # 查看当前掩码值 umask 027 # 临时设置(重启后失效)第八部分:粘滞位(Sticky Bit)—— 共享目录中的隔离墙
问题场景
假设有一个多人共享目录/shared,权限为rwx rwx rwx(777):
- whb 创建了
whb_report.txt(属于 whb) - 另一个用户 maisui 进入
/shared,可以删除whb_report.txt!😱
为什么?因为目录的 w 权限给了 other,允许"在目录内删除文件"。
矛盾点
我需要 other 有 w 权限 → 这样才能在共享目录里创建文件 但我又不想 other 删我的文件 → w 权限允许删任何人的文件怎么办?
粘滞位登场
chmod o+t /shared # 给目录的 other 加上粘滞位 # 或 chmod +t /shared # 简写,默认加到 other 上加上粘滞位后,目录的 other 权限位从x变为t:
drwxrwxrwt 2 root root 4096 Aug 3 18:00 shared/ # ↑ 注意这个 t,说明粘滞位已生效粘滞位的规则:在设置了粘滞位的目录下 —
| 谁能删除文件? | 条件 |
|---|---|
| root(超级用户) | ✅ 永远可以 |
| 目录拥有者 | ✅ |
| 文件拥有者 | ✅ |
| 其他用户 | ❌ 即使有 w 权限也不能删别人的文件 |
🎯 满足"既能让大家共享,又保护每个人创建的文件不被别人删除"。
典型应用
Linux 的/tmp目录默认就设置了粘滞位:
$ ls -ld /tmp drwxrwxrwt 20 root root 4096 Aug 3 18:00 /tmp/ # ↑ 看到 t 了吧第九部分:通配符*—— 批量操作的利器
跟权限搭配的常用姿势:
ls *.c # 列出所有 .c 结尾的文件 ls te* # 列出所有 te 开头的文件 chmod 644 *.txt # 批量修改所有 .txt 文件的权限 rm *.tmp # 删除所有 .tmp 文件📌
*代表"任意字符,任意长度"。*.c= 所有以.c结尾的文件,te*= 所有以te开头的文件。
总结:一张图看清全部
权限位完整解读
- rw- r-- r-- │ │ │ │ │ │ │ └── other(o):4 = r-- │ │ └──────── group(g):4 = r-- │ └────────────── user(u):6 = rw- └─────────────────── 文件类型:- = 普通文件 数字表示:644命令速查表
| 命令 | 作用 | 示例 |
|---|---|---|
su | 切换用户 | su - alice |
sudo | 单条命令提权 | sudo vim /etc/hosts |
chmod 符号法 | 修改权限(加减) | chmod u+w test.txt |
chmod 数字法 | 修改权限(数字) | chmod 755 script.sh |
chown | 修改拥有者 | chown alice:dev test.txt |
chgrp | 修改所属组 | chgrp dev test.txt |
umask | 查看/设置权限掩码 | umask 027 |
chmod +t | 设置粘滞位 | chmod +t /shared |
关键认知集锦
- 权限只验证一次:u → g → o 顺序匹配,匹配到就停,不取最大值
- 目录的 rwx ≠ 文件的 rwx:目录的 w 管增删改名,文件的 w 管内容修改
- 删除文件与文件权限无关,与目录权限有关:你能否删一个文件,取决于你对目录有没有 w 权限
- 最终权限 ≠ 起始权限 - umask:是位运算
起始权限 & (~umask) - 粘滞位只对 other 生效:
chmod +t和chmod o+t是等价的 - chown/chgrp 只有 root 能做:文件的拥有者也不能把文件送人
📚最好的学习方式:开一个终端,用
touch a.txt建个文件,然后把本文中的每条chmod、chown、umask命令都敲一遍,每次改完用ls -l看变化。权限这东西,敲 10 分钟就全记住了。
本文力求为初学者提供准确、全面、易理解的 Linux 权限知识体系。如有疏漏,欢迎指正。
