权限
权限解决的是对于某资源的访问是能还是不能的问题。Linux是多用户操作系统,会有多个用户同时登录,而权限的本质是为了更好的进行用户管理。
用户
Linux中有两类用户,一类是超级用户root ,另一类是普通用户。
- 超级用户root不受任何权限的约束,属于Linux系统中的特权级别
- 普通用户受权限约束
普通用户可以通过输入指令切换成超级用户。
- 语法:
su root输入root用户的密码(不回显) [Ctrl]+D回退到普通用户
普通用户与普通用户之间相互切换需要输入密码进行身份认证,但是root用户切换到其他普通用户时不需要输入密码,这是root用户的特权。
普通账号可以通过sudo指令提权,提权之后可以执行一些普通用户没有权限执行的命令,例如:
cp hello.txt /user/bin/在系统路径下拷贝文件时普通用户没有权限,但是加上sudo cp hello.txt /user/bin/之后,就有权限进行操作。
但是一般情况下,大部分普通用户都不被系统允许执行sudo指令,这是因为在系统内存在一个由root账户维护的白名单sudoers,
路径在/etc/sudoers下,只有在这个名单上的用户才被允许使用sudo指令,只有root用户有权限对白名单进行增删改查。
角色
权限是依附于角色的,一个账户的角色决定了他的权限。
在Linux系统下通常存在三种角色:
- (文件的)拥有者角色:文件的创建者、拥有者
- 所属组角色:与拥有者属于同一组,不是文件的拥有者,但是组内成员均可对文件进行操作
- other角色:无权限对文件进行操作的角色统称为other
Linux
ls指令所列举的文件属性:
-rw-rw-r-- 1 niko niko 0 4月16日 20:48 hello.txt
^ ^
| |
文件的拥有者 文件的所属组
文件属性
文件常见的权限属性有三个:
- 可读(r):
- 可写(w):
- 可执行(x):
Linux
-rw-rw-r-- 1 niko niko 0 4月16日 20:48 hello.txt
前缀-rw-rw-r--显示的是该文件的众多属性,除第一列外,其余列三三为一组,其中,
- 第一列表示文件的类型
-表示普通文件,如源代码、文本、动静态库、可执行文件等d表示目录l表示链接文件p表示管道文件c表示字符文件b表示块设备文件
- 第一组
rw-代表拥有者权限 - 第二组
rw-代表所属组权限 - 第三组
r--代表other权限
每组中,第一个位置表示是否可读,第二个位置表示是否可写,第三个位置表示是否可执行。这三个位置顺序不能乱,必须是可读、可写、可执行。
如果可读,就在第一个位置上标识r,如果不可读,就用-表示,后两个位置也是一样。
权限的指令操作
只有文件的拥有者和超级用户root才能修改文件的权限。
chmod指令可用于修改文件的权限。
- 语法:
chmod [角色][操作][权限] [文件名] - 角色:
u拥有者,表示修改拥有者的权限g所属组,表示修改所属组的权限oother,表示修改other的权限a所有人,包括拥有者、所属组、other
- 操作:
-表示去掉某个权限+表示加上某个权限
- 权限:
r可读w可写x可操作
一个文件要被执行,需要同时满足两个条件:1. 文件本身具备可执行的内容(如二进制程序或有效的脚本) 2. 文件具有可执行权限
这里要区分两个概念:可执行权限 ≠ 可执行文件 。可执行权限是系统对用户的允许标志,可执行文件是诸如二进制程序、有效脚本等能被系统执行的文件。
给一个普通文件添加可执行权限,并不会将它变成可执行文件 ;权限只是允许执行,但系统仍然会因为文件内容无法执行而失败。
去掉拥有者的可读权限
chmod u-r test.txt
去掉拥有者的可读、可写、可执行权限
chmod u-rwx test.txt
添加拥有者的可读权限
chmod u+r test.txt
添加拥有者的可读、可写、可执行权限
chmod u+rwx test.txt
去掉所有人的可读权限
chmod a-r test.txt
去掉所有人的可读、可写、可执行权限
chmod a-rwx test.txt
添加所有人的可读权限
chmod a+r test.txt
添加所有人的可读、可写、可执行权限
chmod a+rwx test.txt
去掉拥有者和所属组的可读权限
chmod u-r,g-r test.txt
需要注意的是,Linux 系统对用户访问文件时的权限验证只进行一次,且按固定顺序:首先匹配文件所有者,其次匹配文件所属组,最后匹配其他用户。
一旦用户身份与文件所有者匹配,系统就直接采用所有者的权限,不再检查用户是否属于文件所属组。
举例来说:如果某个用户既是文件的所有者,又是文件所属组的成员,而所有者的权限为---(不可读、不可写、不可执行),即使所属组的权限为rwx,系统仍然会以所有者的---为准,拒绝该用户的操作。
chown指令可用于修改文件的拥有者。
-
语法:
chown [角色] [文件]将文件的拥有者改成root
chown root test.txt
chgrp指令可用于修改文件的所属组。
-
语法:
chgrp [角色] [文件]将文件的所属组改成root
chgrp root test.txt
只有超级用户 root 能修改文件拥有者,修改所属组时,普通用户(包括文件的拥有者)只能改到自己属于的组,root 则没有限制。
当普通用户修改所属组时有一个隐含的前提:即当前用户必须是该文件的拥有者。
场景模拟
假设有一个用户 张三,他是以下成员:
- 主要组:zhang_group (他的默认组)
- 附加组:project_a、project_b
| 文件 | 当前所属组 | 拥有者 | 张三能否修改? |
|---|---|---|---|
file1.txt |
root |
张三 | ✅ 能 |
file2.log |
project_a |
张三 | ✅ 能 |
file3.sh |
adm (系统组) |
张三 | ✅ 能 |
张三运行命令,把所有文件都改成自己的主要组:
chgrp zhang_group file1.txt file2.log file3.sh
结果:全部成功。
- 虽然
file1.txt原来属于root组 - 虽然
file3.sh原来属于adm组
但因为拥有者是他 ,他就有权把这些文件全部迁移到zhang_group名下。
唯一的限制是 他不能把这些文件改成他不属于的组。例如,如果他不在wheel组里,想改成wheel就会失败。
# 假设张三不在 wheel 组
$ chgrp wheel file1.txt
chgrp: invalid group: 'wheel' # 或者 Operation not permitted
修改文件权限时的八进制方案
在实际操作时,我们发现用户对文件的某个权限总是两态的:可读(r)不可读(-),可写(w)不可写(-),可执行(x)不可执行(-)。
因此,可以用一个八进制数来表示一个角色(拥有者/所属组/other)的完整权限组合,具体来说:
用1表示该用户具有这个权限,0表示不具有这个权限
- rw- rw- r--
二进制 110 110 100
八进制 6 6 4
第一组110就表示拥有者对这个文件可读、可写、不可执行,第二组110表示所属组成员对这个文件可读、可写、不可执行,第三组100表示other可读、不可写、不可执行。
将这三组二进制数组合在一起形成一个八进制数的组合664,它的含义就是拥有者110,所属组110,other100。
同时也可以简化到指令中:
去掉所有角色的所有权限
chmod 000 test.txt
加上所有角色的权限(111 111 111 -> 777)
chmod 777 test.txt
所有角色保留读写(110 110 110 -> 666)
chmod 666 test.txt
只保留拥有者的读权限(100 000 000 -> 400)
chmod 400 test.txt
···
关于权限的面试题
问题一:进入一个目录需要什么权限?
进入一个目录需要x(执行)权限。
r:可列出目录内容(读取目录下文件的名称)。w:可在目录内创建/删除/重命名文件或子目录(需同时有x)。x:可进入目录(cd),或通过路径访问其内部文件/子目录。
目录本身是一种特殊文件,有自己的属性和内容。它的内容保存的是"其他文件的名称 + inode 映射"。
新建文件不只是建"内容",也是在目录里新建一条"属性记录"。因此,新建/删除文件,本质是在修改目录的"内容",故需要目录的w权限。
问题二:为什么新建一个文件(或目录)默认权限是-rw-rw-r--?
在 Linux 系统中,新建一个普通文件或目录时,操作系统并不会直接使用其起始权限 (base permission)作为最终权限,而是会结合权限掩码(umask) 进行修正。其设计目的是为了提供灵活的权限默认控制机制。
- 起始权限的定义
- 普通文件 的起始权限为
666(即-rw-rw-rw-),这是因为文件通常不需要可执行权限。 - 目录 的起始权限为
777(即drwxrwxrwx),因为目录需要可执行权限才能被用户进入。
然而实际观察到的权限往往不同,例如:
-rw-rw-r-- 1 niko niko 0 4月23日 19:48 test.txt # 权限 664
drwxrwxr-x 2 niko niko 4096 4月23日 19:47 test/ # 权限 775
- 权限掩码(
umask)
命令行输入指令umask可以查看本台机器的权限掩码。umask是一个四位的八进制数,通常我们只关注后三位(即权限部分)。
例如0002,其中002为有效掩码。其作用是指出哪些权限位应从起始权限中移除。
公式表示为:
最终权限final=起始权限base & ∼umask \text{最终权限}{\text{final}} = \text{起始权限}{\text{base}} \ \&\ \sim \text{umask} 最终权限final=起始权限base & ∼umask
其中:
&表示按位与操作(bitwise AND)~表示按位取反(bitwise complement)
- 计算示例(以普通文件为例,目录的计算过程完全相同)
- 起始权限:
0666→ 二进制110 110 110 umask:002→ 二进制000 000 010umask按位取反:111 111 101
按位与计算:
起始权限0666 的二进制为 110 110 110,umask码的二进制为 000 000 010。
110 110 110(0666)& 111 111 101(∼002) 110 110 100(0664) \begin{aligned} &\ 110\,110\,110 \quad (0666) \\ \&\ &\ 111\,111\,101 \quad (\sim002) \\ \hline &\ 110\,110\,100 \quad (0664) \end{aligned} & 110110110(0666) 111111101(∼002) 110110100(0664)
结果为0664,对应权限 -rw-rw-r--。
- 结论
默认权限由以下公式统一决定:
permfinal=permbase & ∼umask \text{perm}{\text{final}} = \text{perm}{\text{base}} \ \&\ \sim \text{umask} permfinal=permbase & ∼umask
其中:
perm_base对文件为0666,对目录为0777umask通常为002(常见用户配置)或022(系统默认)
该机制实现了权限的默认降权,提高系统安全性,同时保留灵活性。
问题三:没有rwx权限,可以删除这个文件吗?(粘滞位问题)
可以。
即使一个文件既不能读、也不能写、也不能执行(没有 rwx 权限),你依然可以删除它。
为什么呢?
因为删除文件,不看文件本身的权限,而是看你是否拥有该文件所在的目录的写权限。
举个例子:
在一个共享目录 /share 下,别人创建了一个文件,权限是 ----------(谁都不能碰)。
但只要你对 /share 这个目录有 wx(写+执行)权限,你就可以删除这个文件。
这就会带来一个问题:
在一个共享目录里,大家本来想"你建你的文件,我建我的文件",结果因为目录是共享的,人人都能删别人的东西,这显然不行。
于是就有了 粘滞位(Sticky Bit)。
粘滞位的作用:
在一个目录上设置了粘滞位之后:
- 每个人仍然可以在目录里新建文件
- 每个人也可以删除/修改自己的文件
- 但不能删除/修改别人的文件(即使你对该目录有写权限)
这就是所谓的:
"既能共享,又不能乱删别人的东西。"
粘滞位通常用于像 /tmp 或共享项目目录这样的场景。
权限示例:
bash
drwxrwsrwt 7 root devteam 4096 3月21日 00:24 samba-share
最后一位 t,就表示这个目录设置了粘滞位(Sticky Bit)。
能删除"别人文件"的人有:
| 角色 | 能否删除 | 原因 |
|---|---|---|
| root (超级管理员) | ✅ 能 | Linux中几乎不受任何权限限制 |
| 该目录的所有者 | ✅ 能 | 目录的主人可以清理自己的地盘 |
| 该文件的所有者 | ✅ 能 | 天经地义,自己的文件自己管 |
核心逻辑总结成一句话:
删除文件,看的是目录的权限 ,而不是文件本身的权限。
粘滞位的作用,就是在目录权限放得很宽的情况下,阻止你删除别人的文件。