这一篇只讲三件事:
- 你是谁 ------ Linux 里的两种用户,
su/su -怎么切换身份,以及它背后的进程原理。 - 你能借谁的权力 ------
sudo,它的白名单机制和提权窗口期。 - 那 9 个权限位是什么 ------ u / g / o、文件类型、r / w / x 对文件和对目录分别意味着什么、怎么用字符和数字表示。
至于"怎么改权限"(chmod / chown / chgrp / umask)和"粘滞位",放到下一篇。
这三章的关系是这样的:
第一章(人)你是谁 ──┐
第二章(人)你能变成谁 ──┴──→ 你的身份,决定你对某个文件算 u / g / o 中的哪一个
第三章(物)权限位本身 ─────→ 那三组 rwx 到底在管什么
所以顺序不能反:先把"人"讲清楚,才知道"物"上的三组权限是写给谁看的。
第一章 人:Linux 只有两种用户,但权限是用来限制普通用户的
1.1 两种身份
| 身份 | 提示符 | 能干什么 |
|---|---|---|
| 超级用户 root | # |
想做任何事,不受限制 |
| 普通用户 | $ |
只能做有限的事 |
先立一句总纲:这套权限机制,本质上是在限制普通用户。 root 只是被"提醒",不是被"限制"------这个判断后面会反复被验证(粘滞位的例外名单里有它,sudoers 里也专门给它留了一句 "Allow root to run any commands anywhere")。
提示符是最快的判断方式,一眼就知道自己现在是哪个身份。
1.2 切换身份:su 和 su -
1.2.1 两个命令,只差一个横杠
bash
su [用户名] # 只切换身份
su - [用户名] # 模拟一次完整登录
差别只有那一横,行为差很远:
su |
su - |
|
|---|---|---|
| 身份 | 换成目标用户 | 换成目标用户 |
| 环境变量 | 保留原用户的 | 换成目标用户的 |
| 当前目录 | 不变 | 切到目标用户的家目录 |
| 本质 | 在外层套一层身份 | 重新登录一次 |
一句话记:su 只换人,su - 换人又换房间。
1.2.2 怎么一眼看出自己站在哪一层
看提示符。提示符的格式是 [用户名@主机名 当前目录]:
bash
[root@VM-0-9-opencloudos ~]# whoami
root
[root@VM-0-9-opencloudos ~]# su zbc
[zbc@VM-0-9-opencloudos root]$ whoami
zbc
重点看第二段提示符:[zbc@VM-0-9-opencloudos root]$
- 用户名已经是
zbc→ 身份换了 - 当前目录还是
root→ 目录没换
用户变了、目录没变,这就是 su 最直观的特征。如果这里用的是 su - zbc,提示符末尾会变成 ~,也就是 /home/zbc。
1.2.3 密码规则
- 普通用户 → root:要输 root 的密码
- root → 普通用户:不用输密码
原因很直白:root 的权限最大,不需要向谁证明自己是谁。
1.3 一个案例看懂 su 和 su - 的真实区别
先接受一个前提:根目录 / 对普通用户没有 r 和 w 权限。(r 和 w 具体指什么,第三章会讲透,这里先当结论用。)
现在让 root 在 / 目录下 su 成 zbc:
bash
[root@VM-0-9-opencloudos ~]# su zbc
[zbc@VM-0-9-opencloudos root]$ mkdir mulu01
mkdir: cannot create directory 'mulu01': Permission denied
[zbc@VM-0-9-opencloudos root]$ ls -al
ls: cannot open directory '.': Permission denied
两条命令都失败了,但失败的原因不一样,这个必须分开记:
mkdir失败 → 对/没有 w 权限,不能在目录里创建东西ls失败 → 对/没有 r 权限,读不出目录里有什么
一个缺 w、一个缺 r,两条报错长得一模一样(都是 Permission denied),但根因完全不同。以后看报错要能拆到这一层。
换成 su - zbc,直接落到自己的家目录,一切正常:
bash
[root@VM-0-9-opencloudos ~]# su - zbc
Last login: Sat Apr 25 18:32:25 CST 2026 on pts/0
[zbc@VM-0-9-opencloudos ~]$ pwd
/home/zbc
[zbc@VM-0-9-opencloudos ~]$ ls -l
drwxr-xr-x 4 zbc zbc 40 Apr 23 15:43 gitcage
-rw-r--r-- 1 zbc zbc 87 Apr 25 14:19 ma6174
-rw-r--r-- 1 zbc zbc 149 Apr 25 14:21 makefile
-rw-r--r-- 1 zbc zbc 0 Apr 25 12:57 PassWordForZbc
因为家目录是 zbc 自己的东西,权限归它。
顺带一条规则:每新建一个用户,系统都会在 /home 下建一个同名目录当他的家目录。 root 是例外,装系统的时候就已经有 /root 了。
1.4 底层原理:su 不是"变身",是"套娃"
这一节是第一章的核心。
1.4.1 关键结论
执行 su 不是把 root 进程改造成 zbc,而是通过 fork() 派生出一个新进程。
第一层(父进程):root 的 shell PID 1001 ← 没消失,只是挂起了
↓ fork()
第二层(子进程):zbc 的 shell PID 1050 ← 前台,终端归它用
所以"切换用户"这个说法其实有点误导------没有任何东西被切换,是多了一个进程。
1.4.2 那父进程去哪了
root 的 shell 没有退出,它做了一件事:把自己挂起,然后调用 wait() 盯着子进程。
它暂时交出了终端的控制权,在后台等着。因为一个终端同一时间只能有一个前台进程,这个位置让给了子进程。
1.4.3 Ctrl+D 为什么能"退回去"
因为它根本不是"回退操作",是自毁操作:
- 子进程(zbc 的 shell)收到退出指令 → 终止 → 内核回收它占用的所有资源
- 一直在
wait()的父进程(root 的 shell)被系统唤醒 - 父进程重新拿到终端的读写权,回到前台
所以不是"退回去",是里面那层塌了,外面那层露出来。
这里有个特别容易搞反的点:Ctrl+D 不是"返回上层用户"的快捷键,它的本意是"结束当前输入"(EOF),顺带成了退出当前 shell 的方式。 之所以看起来像"返回",是因为上层本来就一直在那儿等着,从来没走。
在这个场景下,Ctrl+D、exit、logout 效果一致。
1.4.4 用 who 验证一下
who 能直接证明"登录的还是 root":
bash
[root@VM-0-9-opencloudos ~]# who
root pts/0 2026-04-26 08:10 (223.104.73.140)
root pts/1 2026-04-26 09:14 (223.104.73.140)
[root@VM-0-9-opencloudos ~]# su - zbc
[zbc@VM-0-9-opencloudos ~]$ who
root pts/0 2026-04-26 08:10 (223.104.73.140)
root pts/1 2026-04-26 09:14 (223.104.73.140)
su 成 zbc 之后,who 里还是没有 zbc。
因为 who 读的是登录记录。 pts/0 这个终端从头到尾都是 root 远程登录时开的,su 只是在别人已经开好的终端里生了个子进程,并没有产生新的登录。
我同学的比喻很准:root 把房子租给了 zbc,但房产证上写的还是 root。
1.5 把这一整套看成栈
既然是一层层套出来的,结构就是栈:
| 状态 | 进程栈内容 | 当前活跃用户 |
|---|---|---|
| 初始 | [ root ] |
root |
su - zbc |
[ root → zbc ] |
zbc(栈顶) |
su - guest |
[ root → zbc → guest ] |
guest(栈顶) |
Ctrl+D |
[ root → zbc ] |
zbc(回到上一层) |
再 Ctrl+D |
[ root ] |
root |
理论上可以无限套下去,每按一次 Ctrl+D 弹一层,直到露出最核心的那个原始进程。
这个模型还能顺手解释一件事:为什么 su 不会破坏原来的登录环境------因为原来那层压根就没动过。
1.6 su 的两个毛病
su 能干的事不少,但有两个硬伤:
- 得知道 root 的密码。 多人协作的环境里,这等于把最高权限的钥匙抄给了所有人,而且给了之后很难收回来(改密码会影响所有人)。
- 粒度太粗。 一旦切过去就是彻底的 root。你可能只是想重启一个服务,却拿到了一整个 root shell,一不小心什么都能干。
第二章的 sudo,就是来解决这两个问题的。
第二章 人:sudo ------ 不换身份,只借一条命令的权力
2.1 一句话分清 su 和 sudo
su:换个人来做。 整个 shell 都变成另一个人,之后你敲的每条命令都是他的。sudo:还是你,但这一条命令以目标用户(默认 root)的身份运行。
| su | sudo | |
|---|---|---|
| 身份 | 真的切过去了 | 没变,还是你 |
| 作用范围 | 切换之后的所有命令 | 只有这一条命令 |
| 要谁的密码 | 目标用户的密码(通常是 root) | 你自己的密码 |
| 权限粒度 | 要么全有,要么全无 | 能精确到"哪个用户在哪台机器上以谁的身份跑哪些命令" |
"sudo 比 su 更安全、更可控"这话不是空话,它就体现在上面这张表的每一行。
2.2 sudo 的两个案例
2.2.1 案例一:跨过那道门
bash
[zbc@VM-0-9-opencloudos ~]$ ls /root
ls: cannot open directory '/root': Permission denied
[zbc@VM-0-9-opencloudos ~]$ sudo ls /root
[sudo] password for zbc:
test
[zbc@VM-0-9-opencloudos ~]$ sudo ls /root
test # 五分钟内再执行,不用输密码
三行输出,三个信息点:
- 第一行:普通用户读
/root直接被拒(和 1.3 里/的情况同理) - 第二行:sudo 让这条命令以 root 身份跑,成了
- 第三行:五分钟窗口期,第二次不用再输密码(2.4 细讲)
注意 sudo 要的是 zbc 自己的密码,不是 root 的。这是它和 su 最根本的区别之一。
2.2.2 案例二:文件归属暴露了真相
这个案例更能说明 sudo 的本质:
bash
[zbc@VM-0-9-opencloudos ~]$ touch test01.c
[zbc@VM-0-9-opencloudos ~]$ sudo touch test02.c
[zbc@VM-0-9-opencloudos ~]$ ls -l test01.c test02.c
-rw-r--r-- 1 zbc zbc 0 Apr 26 10:12 test01.c
-rw-r--r-- 1 root root 0 Apr 26 10:12 test02.c
两个文件都是 zbc 敲出来的,但第二个归 root。
这条现象把 sudo 的底层含义直接摆出来了:提权不是给 zbc 贴了一个"特权"标签,而是这次操作换了个身份去执行。
文件是 root 创建的,所有者就写 root------ls -l 里的所有者和所属组那两列不会撒谎。
反过来说,这里埋了一个坑:用 sudo 创建或修改过的文件,普通用户自己反而改不动了,因为它的所有者变成了 root。(怎么改回来,是下一篇 chown 的事。)
2.3 /etc/sudoers:权力白名单
"凭什么别人 sudo 可以,我不行?"------不是不行,是你没被写进白名单。
2.3.1 为什么普通用户打不开它
白名单就是 /etc/sudoers:
bash
[root@VM-0-9-opencloudos ~]# vim /etc/sudoers
# 必须以 root 用户打开,其他用户打开什么都看不到
那句话要单独理解:不是文件不存在,是你没有读它的权限。(对照第三章:读一个文件需要 r 权限。)
2.3.2 格式怎么读
找到这一行:
## Allow root to run any commands anywhere
在它下面加上一行:
zbc ALL=(ALL) ALL
四个字段拆开看:
zbc ALL = (ALL) ALL
↑ ↑ ↑ ↑
用户名 允许登录的主机 可切换的身份 允许执行的命令
按字面读就是:zbc 可以从任何主机登录,以任何用户(包括 root)的身份,执行任何命令。
(ALL) 那一栏是 sudo 最精细的地方------你可以把它收窄,比如只允许以 root 的身份跑某几个具体命令,这就是所谓的"权限精细化管理"。
2.3.3 NOPASSWD:免密
这个文件里还能加 NOPASSWD 标记,让某个用户执行 sudo 时完全不用输密码。
它和 2.4 那个"五分钟窗口期"是两回事:窗口期是暂时的(几分钟自动过期),NOPASSWD 是长期的(写进配置就一直有效)。
用哪个,取决于你把"安全"和"方便"的秤砣放在哪一边。
2.3.4 另一种改法,和一个作死行为
课件里还给了另一种写法------先把权限放开再改:
bash
# chmod 740 /etc/sudoers
# vi /etc/sudoers
以及 sudo 的调用形式:
bash
$ sudo -u 用户名 命令
$ sudo -u root /usr/sbin/useradd u21 # 以 root 身份执行 useradd
-u 就是在说"这次以谁的身份跑",不写默认 root。
最后记一个作死行为(知道就行,别试):把 sudoers 里 root 那一行删掉,等于让 root 自己失去大量权力,会搞出一个很尴尬的局面。
2.4 提权窗口期
规则:第一次执行 sudo 时输密码,之后五分钟是一个窗口期,窗口期里再执行 sudo 不用输密码。
这是"安全"和"好用"之间的折中------否则你连着敲十条 sudo 就要输十遍密码。
2.5 综合案例:把一个程序"装"进系统
课件里这个案例一次性串起了好几件事,很适合给第二章收尾:
bash
[zbc@VM-0-9-opencloudos ~]$ cp test /usr/bin
cp: cannot create regular file '/usr/bin/test': Permission denied
[zbc@VM-0-9-opencloudos ~]$ sudo cp test /usr/bin
[sudo] password for zbc:
[zbc@VM-0-9-opencloudos ~]$ test # 现在直接敲名字就能跑了
[zbc@VM-0-9-opencloudos ~]$ sudo rm -f /usr/bin/test
拆开看,四件事:
- 为什么自己编译的程序要用
./test,系统命令却直接敲名字就行?
因为系统命令放在/usr/bin里,而/usr/bin在 PATH 里。PATH 是系统"去哪找命令"的那份地址清单,.(当前目录)通常不在清单上,所以你得手动加./告诉 shell:就在当前目录。 - 为什么
cp到/usr/bin需要管理员权限?
因为把文件放进/usr/bin,效果上就等于"装了一个命令"。普通用户装不进去,是权限拦住的------这个拦截是对的。 - 装上去之后谁都能用。
任何一个用户在同一台机器上装的命令,所有人都能用(除了某些只有 root 能用的特殊命令)。 - 用完记得删掉。
sudo rm -f /usr/bin/test,不然它就真的留在系统里了。
到这里,"人"这条线走完:你是谁 → 你能变成谁 → 你能借谁的权力。
接下来是"物"------那些权限位到底在说什么。
第三章 物:那 9 个权限位到底在说什么
前面一直在喊 "Permission denied",现在把权限本身拆开看。
3.1 访问者分类:u / g / o
任何文件,站在它面前的人只分三种:
| 符号 | 含义 | 记忆 |
|---|---|---|
u |
User,文件的所有者 | 中国平民(因为有法律问题) |
g |
Group,所有者所在组的用户 | 同组同事 |
o |
Others,其他用户 | 外国人 |
你现在是什么身份,决定你在这三者里算哪一个。 这就是为什么前面非得先把"人"讲清楚------那三组权限,本来就是写给三种不同的人看的。
举个例子,-rw-rw-r--:
- 所有者(u)能读能写
- 同组(g)能读能写
- 其他人(o)只能读
3.2 文件类型:第一个字符
ls -l 输出的第一列一共 10 个字符,第一个是类型,后面 9 个是权限:
| 字符 | 类型 |
|---|---|
d |
目录 |
- |
普通文件 |
l |
软链接(类似 Windows 的快捷方式) |
b |
块设备文件(硬盘、光驱等) |
c |
字符设备文件(屏幕等串口设备) |
p |
管道文件 |
s |
套接字文件 |
3.3 完整解剖一行 ls -l
先把第一列拆开:
bash
-rw-rw-r-- 1 whb whb 0 Jan 11 14:22 file.txt
↑ ↑↑↑ ↑↑↑ ↑↑↑
| | | └── 其他人(o):r-- 只读
| | └────── 同组(g):rw- 读 + 写
| └────────── 所有者(u):rw- 读 + 写
└───────────── 文件类型:- 普通文件
再看一整行的完整结构:
d rwx rwx r-x 3 whb whb 4096 Jan 11 15:01 file.txt
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
类型 所有者 同组 其他人 链接数 所有者 所属组 大小 最后修改时间 文件名
这张图值得记住,后面所有关于权限的讨论都是在这上面展开的。
3.4 r / w / x:同一个字母,含义完全不同
这一节是第三章的核心,也是整个权限体系里最容易搞错的地方。
| 权限 | 对文件 | 对目录 |
|---|---|---|
r (4) |
读取文件内容 | 浏览目录里有什么(能不能 ls) |
w (2) |
修改文件内容 | 在目录里创建 / 删除 / 移动文件 |
x (1) |
把文件当程序执行 | 进入 这个目录(能不能 cd) |
- |
没有该权限 | 没有该权限 |
逐个拆:
r ------ 读
- 对文件:能打开看内容
- 对目录:能列出里面有哪些文件(
ls)
w ------ 写
- 对文件:能改内容
- 对目录:能在里面创建、删除、移动 文件
← 注意,这里管的是"目录里有什么东西",不是文件内容
x ------ 执行
- 对文件:能被当作程序运行
- 对目录:能进去(
cd)
3.4.1 由这张表推出的三条结论
- 目录没有 x 就进不去。 哪怕它有 r 权限也没用。
这是最容易搞错的一条------很多人以为"有读权限就能进目录看文件"。不行,cd需要的是 x。 - 有 x 但没有 r :能
cd进去、能在里面执行命令,但ls读不出目录内容。
合起来说就是:你能干活,但看不见活在哪。 - 只要你对目录有 w,你就能删掉目录里的任何文件------不管你对该文件本身有没有权限。
这条是权限设计上的一个洞。(怎么补它是下一篇粘滞位的事,这里先记住"有这么一个洞"。)
3.4.2 回到第一章那个案例
现在回头看 1.3 里 / 目录打不开的情形,就通了:
bash
[zbc@VM-0-9-opencloudos root]$ mkdir mulu01
mkdir: cannot create directory 'mulu01': Permission denied # 缺 w
[zbc@VM-0-9-opencloudos root]$ ls -al
ls: cannot open directory '.': Permission denied # 缺 r
mkdir要在目录里创建东西 → 需要目录的 wls要读出目录里有什么 → 需要目录的 r
第一章埋的伏笔,在这里收掉。
3.5 权限的两种记法
3.5.1 字符法
就是看到的那 9 位,分成三组:
rwx rw- r--
↑ ↑ ↑
所有者 同组 其他人
3.5.2 8 进制法
把每组三位当成数字来算:
r = 4 w = 2 x = 1 (没有就是 0)
三个一组分别相加,每组得到 0~7:
| 权限 | 值 | 含义 |
|---|---|---|
rwx |
7 | 读 + 写 + 执行 |
rw- |
6 | 读 + 写 |
r-x |
5 | 读 + 执行 |
r-- |
4 | 只读 |
-wx |
3 | 写 + 执行 |
-w- |
2 | 只写 |
--x |
1 | 只执行 |
--- |
0 | 什么权限都没有 |
为什么是 4 / 2 / 1?因为三个权限位各自独立、互不重叠,用二进制写出来正好是 100 / 010 / 001,加起来不会有歧义。这就是权限数字能用一个 0~7 表示一位的原因。
3.5.3 常见的几种组合
| 8 进制 | 等价字符 | 典型场景 |
|---|---|---|
644 |
rw-r--r-- |
普通文件 |
664 |
rw-rw-r-- |
同组可写的文件 |
640 |
rw-r----- |
只给同组看 |
700 |
rwx------ |
只给自己 |
755 |
rwxr-xr-x |
目录、可执行文件 |
777 |
rwxrwxrwx |
全开,危险 |
看这几个数字有个小技巧:第一位(所有者)几乎总是 6 或 7,真正决定"这份文件敞开多少"的是后两位(同组、其他人)。
3.6 file 指令:先认清它是什么
bash
file [选项] 文件或目录...
-c 详细显示指令执行过程,便于排错或分析程序执行的情形
-z 尝试解读压缩文件的内容
命令本身不复杂,但它的位置很重要:先知道这是什么东西,再决定该给它什么权限。
对着一堆来路不明的文件直接 chmod 755,是很多麻烦的开端。
本篇小结
第一章 + 第二章(人)
| 命令 | 作用 | 关键点 |
|---|---|---|
su 用户 |
切换身份 | 只换人:环境变量、当前目录都不变 |
su - 用户 |
模拟完整登录 | 换人又换房间:家目录、环境变量全换 |
sudo 命令 |
以 root 身份执行这一条 | 输自己的密码;五分钟窗口期 |
sudo -u 用户 命令 |
以指定用户身份执行 | -u 指定身份 |
vim /etc/sudoers |
改白名单 | 用户 主机=(身份) 命令;必须 root 打开 |
Ctrl+D / exit |
退出当前 shell | 自毁当前进程,外层弹回来 |
第三章(物)
| 值 | 字符 | 值 | 字符 |
|---|---|---|---|
| 7 | rwx |
3 | -wx |
| 6 | rw- |
2 | -w- |
| 5 | r-x |
1 | --x |
| 4 | r-- |
0 | --- |
三条必须记住的结论
su不是变身,是 fork 出一个子进程;Ctrl+D是自毁内层,不是回退。sudo不改身份,只是让这一条命令换个身份执行------所以它创建的文件归 root。rwx对文件和目录含义完全不同,尤其是:目录的 w 管的是"能不能删掉里面的任何文件"。
下一篇:怎么改权限 ------ chmod / chown / chgrp / umask,以及粘滞位怎么补上 3.4.1 第三条那个洞。