1、UID和GID
在Linux中每个文件都有一个UID和GID。
默认情况下,文件的所有者 (UID):自动设置为创建该文件的用户的 UID。所属组 (GID):自动设置为该用户的主组 。
用户根据文件的UID和GID来判断自己是否有相应的访问权限。
系统根据文件的UID 和GID,对比用户的UID和GID来决定用户的访问的权限。
进程也会继承运行它的用户的权限。
文件权限的匹配原则:
UID ——> GID ——>Other
用户的UID匹配文件的UID——> 则以文件的UID身份(文件的拥有人)的权限进行访问
用户的GID匹配文件的GID——>则以文件的GID身份(文件的拥有组)的权限进行访问
用户的UID和GID均无法匹配到文件的UID和GID,则以文件拥有人和拥有组之外的other身份(其他人)的权限进行访问
root 用户无视文件权限的匹配规则
2、查看文件权限
ll或stat列出的文件权限
[root@openEuler opt]# ls -l zhangsan.txt
-rw-r--r--. 1 root root 0 Jul 14 14:41 zhangsan.txt
-: 第一列(-rw-r--r--)的第一个字符表示文件类型,表示文件的类型
-:表示普通文件
d:表示目录 (Directory)
l:符号链接 (Link)
c:字符设备 (Character),逐个字符读取的设备,如键盘、串口、虚拟终端
b:块设备 (Block),按数据块随机读取的设备,如硬盘、U 盘
s:套接字 (Socket),用于网络或本地进程间通信的文件
p:管道 (Pipe/FIFO),用于进程间传递数据
rw-r--r--:剩余的九个字符表示文件或者目录的权限
r:表示读取权限(readable)
w:表示写入权限,删除也需要有w权限(writable)
x:表示执行权限(executable)
-:表示没有对应权限
rw-:前三个表示文件的拥有人权限,该文件的拥有者可读、可写,不可执行
r--:中间三个表示文件的拥有组权限,该文件的所属组用户可读、不可写、不可执行
r--:后三个文件的其他用户权限,不是拥有者和所属组的用户可读、不可写、不可执行
.: seLinux的安全标记,表示文件受到seLinux的保护
1: 表示文件的硬链接数
root: 表示文件的UID也就是拥有人
root: 表示文件的GID也就是拥有组
0:表示文件的大小,如果为0则表示是一个空文件
Jul 14 14:41: 文件最后一次被修改的时间
zhangsan.txt: 文件名权限对于文件和目录的含义
在Linux中一个目录要具有意义,则该目录最少需要有r和x权限,表示用户可以进入到该目录下,正常的读取到文件。假如一个目录只有r权限却没有x权限,因为拒绝进入目录,ls命令无法完成查找,依然无法列出其中的内容。
能否删除一个文件,决定性因素是该文件所在文件夹(目录)的写权限(w),而与文件本身的权限关系不大。
当对一个文件进行修改/编辑,操作文件本身时,查看【文件的权限】。
创建一个文件/删除一个文件,则要查看文件所在【目录的权限】。
普通用户作为文件的拥有人时,可以修改文件的所属组,但无权修改文件的所有者。
3、数字方式表示权限
使用数字4表示r读取权限,数字2表示w写入权限,数字1表示执行权限,0表示无权限
字母:r w x
数字:4 2 1
使用三位数字就可以表示文件的拥有人、拥有组、其他人权限
如:751 = rwx r-w --x
第一位是拥有人r+w+x的和(rwx之和,4+2+1=7)
第二位是拥有组r+w+x的和(r和w之和,4+1=5)
第三位是其他用户r+w+x的和(只有x,1)
为什么是用 4、2、1 来表示?
Linux 为读、写、执行这三种操作分配了二进制中的三个位置,权限:有(1)/ 无(0)
读 (r):分配在最高位(左边的位),二进制是
100。换算成十进制:1×22=4
写 (w):分配在中间位,二进制是
010。换算成十进制:1×21=2
执行 (x):分配在最低位(右边的位),二进制是
001。换算成十进制:1×20=1
任意组合相加,结果都是唯一的,不会重复。
4、权限管理
chmod 修改文件/目录权限
root用户可以修改所有人的文件权限;普通用户只能修改自己的文件权限
字符方式赋权
拥有人——>u 拥有组 ———> g 其他人 ——> o
u+g+o=a=all 所有人
格式:
chmod [用户类别][+|-|=][权限] filename ,操作多个对象使用','隔开
加减赋权:
+/- 都是在文件的原权限基础上进行加减赋权,因此如果权限设置错误,则可以通加减的方式还原
chmod u+r,g+w,o+x filename
chmod ugo+r filename
chmod a+r filename
chmod +r filename
(理论上和a+r一样,强制给所有人加读取权限,但是简写的写法会受到权限掩码umask的限制)
chmod u-w,g-x,o-r filename
chmod ugo-r filename
chmod -x filename
(简写的a-x一样要受到umask限制,只不过默认情况刚好两者作用相同)
精确赋权:
使用等于号来指定赋权,会覆盖原有的权限,一旦权限设置错误则很难找回
chmod u=r,g=w,o=x filename数字方式赋权
数字的方式也会对权限造成覆盖
格式:chmod 三位数字 文件/目录
eg: chmod 666 file
第1位拥有人的权限;拥有人有4+2 也就是读、写权限
第2位是拥有组的权限;拥有组有4+2 也就是读、写权限
第3位是其他人的权限;其他人有4+2 也就是读、写权限chmod -R给一整个文件夹递归赋权
chmod -R 755 /path/to/your/folder
chmod -R a+r /path/to/your/folderchown 修改拥有人/拥有组
chown 拥有人:拥有组 文件
中间的连接符号冒号:也可以换成点 .
但是容易产生迷惑,一般还是用冒号
chown username:groupname filename 修改文件的拥有人以及文件的拥有组
chown username filename 仅修改文件的拥有人
chown :groupname filename 仅修改文件的拥有组同样的,chown -R 来递归修改整个文件夹
chgrp 修改拥有组
chown(Change Owner):既管“人”也管“组”。chgrp(Change Group):只管“组”,可以被chown替代。chgrp 用户组 文件/目录同样的,
chgrp -R来递归修改整个文件夹
5、权限掩码UMASK
umask (权限掩码)用来控制用户默认创建的文件/目录的默认权限
所有新建目录,程序天然申请的最大权限是 777。
所有新建文件,程序天然申请的最大权限是 666
然后,系统用同一个 umask(比如 022) 去做减法(掩码过滤):
建目录时:777 减去 022 = 755
建文件时:666 减去 022 = 644
让文件默认具有可执行权限不安全,所以文件的默认最大值只有666,这样umask怎么设,-都不会默认可执行
查看用户的umask值:umask
设置umask值:
先确定umask值,假设我们要让目录:拥有人RWX/拥有组RWX/其他人R-X
以数字方式表示为:775
umask值为:目录可申请最大值777 - 775 得 002
假设我们要让文件:拥有人RW-/拥有组R--/其他人R--
以数字方式表示为:644
umask值为:文件可申请最大值666 - 644 得 022
当发现目录和文件计算的umask值冲突,应该以目录的值为准,因为其值影响其下所有文件和子目录的可访问性,而文件的权限可以自己单独再修改。
“奇数位加 1”规则:
计算文件权限时,当 umask 值的某一位是奇数时,计算出的最终权限在对应位上需要加 1。
假设umask 是 055,计算结果为666-055得611,055的后两位55是奇数,那么计算得出的611的后两位也要加1,最终的结果是622。
登录/非登录/当前/子Shell
要完全理解各种修改umask的方式的不同,需要提前了解Shell相关的知识。
在Linux/Unix系统中,Shell是用户与Linux内核之间的命令解释器,它接收用户输入的命令,解析后传递给内核执行,并将结果返回给用户。
用户 → Shell → Kernel → 硬件
登录/非登录/当前/子Shell的Shell指的都是命令解释器
是否为登录Shell主要看密码:输入了密码进来的就是登录 Shell,直接弹出来的就是非登录 Shell。它们的区别在于读取哪个配置文件。
输入
echo $0如果输出的是-bash说明是登录shell,如果输出的是bash则说明是非登录Shell
登录 Shell:加载了完整环境配置文件/初始化环境的 Shell
图形化界面/字符界面输入密码登录
通过 SSH 远程连接到服务器(输入了密码)。
按 Ctrl+Alt+F3 切到纯黑底白字的物理终端,输入账号密码登录。
输入
su - 用户名彻底切换身份,sudo -i切换root身份登录Shell会触发的变量文件(触发顺序由上至下):
/etc/bashrc
/etc/profile
~username/.bashrc
~username/.bash_profile
非登录Shell:复用了父进程环境变量/局部初始化的 Shell
在图形桌面里双击打开了一个“终端”窗口。
在终端里敲了一个 bash 命令,又开了一个 Shell
输入
su 用户名切换用户,sudo执行命令(不论是否需要密码)非登录Shell会触发的变量文件:
/etc/bashrc
~username/.bashrc
其中,/etc/bashrc和/etc/profile 是全局变量文件,而~username/.bashrc 和
~username/.bash_profile 是用户的变量文件
通过两者对比可以得出结论:
不管是登录shell还是非登录shell,如果想要指定用户触发变量文件的内容的话,写入~username/.bashrc文件
不管是登录shell还是非登录shell,如果想要系统所有的用户都生效的话,写入/etc/bashrc文件
补充:用户的登出shell触发的变量文件是~username/.bash_logout
当前Shell:接收你当前键盘输入指令的那个 Bash Shell进程。
子 Shell:是继承当前 Shell 环境的副本,但在其中执行的命令所产生的变量赋值和环境改变,不会影响父 Shell 环境。其意义是变量和操作不会互相干扰。
常见的产生子Shell的场景(以下5种均属于非登录Shell):
在当前终端输入
bash命令管道符右侧的操作,如
ls | grep txt通过直接执行的方式运行一个脚本
./script.sh圆括号组内的所有命令在子 Shell 执行,不影响主Shell
(cd /tmp; ls)命令放入后台执行
sleep 100 &
在当前 Shell 的“子进程”中运行。:
vim, python, ls等
修改umask
当手动输入umask 值 来设置时,只影响当前 Shell和所有子进程/子 Shell,当执行exit出当前终端或者重启时失效。
永久修改:
直接写入配置文件:umask 022
不管是登录shell还是非登录shell,如果想要系统所有的用户都生效的话,写入/etc/bashrc文件
不管是登录shell还是非登录shell,如果要想指定用户生效,写入到 ~username/.bashrc文件
条件赋值:
如果用户 ID 大于 199(通常是普通用户)且用户名和组名相同,则使用 umask 002(文件权限 664),否则(如 root 用户)使用 umask 022。
if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
umask 002
else
umask 022
fi[ $UID -gt 199 ] 检查当前用户的用户 ID 是否大于 199。
[ /usr/bin/id -gn" = /usr/bin/id -un" ]
id -un:打印当前用户的用户名。
id -gn:打印当前用户的主组名。
判断用户名和主组名是否一致,如果一致说明用户就是它的主组的所有者,则可以给更宽松的权限
6、特殊权限
suid权限
对文件:如果某个二进制文件带有suid权限,那么执行这个文件会以文件的拥有人的身份去执行(使用场景一般是程序,不包括shell脚本)
对目录:suid特殊权限对于目录来说是没有任何意义的
suid对应的数字为4:
使用4位数字表示权限(例如 4755,第一位就表示特殊权限)
如果没有权限,则第一位为0,如0755
设置特殊权限:
chmod 字母:
chmod u+s /usr/bin/touch 添加
chmod u-s /usr/bin/touch 删除
chmod 数字
chmod 4655 /usr/bin/touch 添加
chmod 0655 /usr/bin/touch 删除
查看特殊权限:
执行ll或者stat时,当看到拥有人的权限x栏位变成了s或者S ,说明这个文件有suid的权限。
如果是小s,说明这个栏位原来是有x权限:
-rwsr-xr-x如果是大S,说明这个栏位原来没有x权限:
-rwSr--r--
sgid权限
对文件:如果某个二进制文件带有sgid权限,那么执行这个文件会以文件的拥有组的身份去执行
对目录:如果某个目录有sgid的权限,那么这个目录下所创建的所有子目录以及文件都会继承目录的拥有组(默认情况下是谁创建文件,所属组就是谁的主组)
suid对应的数字为2
设置特殊权限:
chmod 字母:
chmod g+s /usr/bin/touch 添加
chmod g-s /usr/bin/touch 删除
chmod 数字
chmod 2655 /usr/bin/touch 添加
chmod 0655 /usr/bin/touch 删除
查看特殊权限:
当看到拥有组的权限x栏位变成了s或者S ,说明这个文件有sgid的权限。
如果是小s,说明这个栏位原来是有x权限
如果是大S,说明这个栏位原来没有x权限
stciky/sbit权限
对文件:没有任何意义
对目录:如果目录有sbit权限,则目录下的文件和目录只有创建者能够修改、删除,不能够去修改或者操作其他人的文件(root用户无视此规则)
sbit权限对应的数字为1
设置特殊权限:
chmod 字母:
chmod o+t /opt 添加
chmod o-t /opt 删除
chmod 数字
chmod 1655 /opt 添加
chmod 0655 /opt 删除
查看特殊权限:
如果其他人栏位的x权限变成了t或者T,表示文件有sbit权限
如果是小t,说明这个栏位原来是有x权限
如果是大T,说明这个栏位原来没有x权限
7、ACL权限
在 Linux 中,引入访问控制列表(ACL, Access Control List)可以指定任意的用户或用户组来设置权限,突破一个文件只能有一个所属用户和一个所属组来管理权限的限制。
设置acl权限
setfacl [选项] [规则] 文件或目录
setfacl -m u:zhangsan:rw- file:修改 file 的权限,用户 zhangsan 对其拥有r和w权限setfacl -m g:zhangsan:rw- file:修改 file 的权限, zhangsan 这个组里的所有成员对其拥有r和w权限-m: 这是 --modify 的缩写,表示修改或添加ACL规则
u:zhangsan:rw-: 权限规则由三部分组成,用冒号 : 分隔
u: 代表用户 (user),指明这条规则是针对一个特定的用户
g: 代表用户组 (group),指明这条规则是针对一个特定的用户组
zhangsan: 第一个例子中u:zhangsan是用户,第二个例子中g:zhangsan是用户组的名字
-R 递归修改整个目录
setfacl -R -m u:xiaoming:rx /data/project-d 该目录新建文件自动继承权限
setfacl -d -m u:xiaoming:rx /data/project
setfacl省略用户和用户组
不特定用户,也不特定用户组,那么setfacl命令就相当于chmod
setfacl -m u::rw- file === chmod u=rw file给拥有人设置acl权限setfacl -m g::rw- file === chmod g=rw file给拥有组设置acl权限
chacl:覆盖式替换原有权限,不推荐使用
# 1. 首先,你需要查看现有的 ACL (使用 chacl -l 或 getfacl)
# 假设现有 ACL 是: u::rwx,g::r-x,o::r--
# 2. 然后,你必须手动构建一个包含新旧所有规则的完整字符串
# 你想添加 u:bob:r--, 所以新字符串是 u::rwx,g::r-x,o::r--,u:bob:r--,m::r-x
# 3. 最后,用 chacl 执行替换
chacl 'u::rwx,g::r-x,o::r--,u:bob:r--,m::r-x' myfile.txt删除acl权限
setfacl -x u:zhangsan file 删除指定用户的acl权限
-x:代表“移除”(remove),意思是从 file 的 ACL 列表中,仅删除关于用户 zhangsan 的那一条权限规则。
setfacl -b file 删除文件的所有acl权限
-b:代表“清除”(blank out),一刀切地删除文件上所有通过 ACL 设置的额外规则,包括acl权限掩码。
查看acl权限
粗略查看:ll file ,如果文件权限后面有 + 表示有acl权限
[root@rhel9 opt]# ll file
-rw-rw-r--+ 1 root root 9 Dec 2 09:21 file
详细查看:getfacl file
[zhangsan@rhel9 ~]$ getfacl /opt/file
getfacl: Removing leading '/' from absolute path names
# file: opt/file # 文件名(以 # 开头的行属于元数据,确认文件信息)
# owner: root # 拥有人
# group: root # 拥有组
user::rw- # 拥有人的权限
user:zhangsan:rw- # zhangsan用户的权限
group::r-- # 拥有组的权限
mask::rw- # 权限掩码
other::r-- # 其他人的权限acl权限掩码
权限掩码的工作方式是通过一个“逻辑与”(AND)运算来过滤权限。只有当 ACL 规则和 mask 都允许某个权限时,该权限才会真正生效。通常不需要手动修改 mask。
设置掩码值
setfacl -m m::rwx file
[zhangsan@rhel9 opt]$ getfacl file
# file: file
# owner: root
# group: root
user::rw-
user:zhangsan:rw- #effective:rw-
group::r--
mask::r--
other::r--mask 权限只会限制以下三类条目的最终有效权限:
命名用户 (如
user:zhangsan)命名用户组 (如
group:devteam)文件所属组 (即
group::)
最终有效权限显示为#effective
如果需要完全取消掩码值,只能setfacl -b file
acl权限的优先级
文件的拥有人
文件的用户acl权限
文件的拥有组的权限
文件的用户组acl权限
文件的其他人
拥有人权限优先级高于用户ACL权限:如果 zhangsan 是文件的所有者,系统直接看
user::(基础rwx权限),完全忽略user:zhangsan的 ACL 条目。例如user::是r--,但user:zhangsan (ACL)是rwx。作为所有者,zhangsan 只有 r-- 权限。组权限是“取并集”:zhangsan 既属于 dev 组(文件所属组),又属于 admin 组(ACL 命名组),
group:: (dev)权限是r--,group:admin (ACL)权限是-w-,最终权限:系统会合并这两个权限,变成rw-(然后再与 mask 运算)。
8、sudo提权
sudo是linux系统中的是一个身份切换和执行工具,sudo提权并不一定是从低到高,是以其他用户(通常是 root)的身份启动一个新进程来执行某个独立的程序。
sudo
-k 强制下次sudo时验证密码(第一次输入密码后,默认5分钟不会要求输入)
-u 以指定用户的身份来执行命令,-g指定用户组身份
-l 列出当前用户的sudo提权配置
-b 放入后台运行 (和 & 符号一样)
-i 是 Linux 系统中用于以 root 用户身份启动一个完整的登录 Shell 的命令
sudo command 执行某个命令时,不论是否需要输入密码,都属于非登录Shell(因为它的密码是验证而非真的登录),而sudo -i 切换到root用户属于登录Shell。不论哪种方式,都不在当前Shell。

图中内容显示:用户 zhangsan 仅被授权以 root 身份执行 /usr/sbin/useradd 这一个命令。他不能使用 sudo 执行其他任何命令。
配置sudo提权:
sudo配置文件:/etc/sudoers
配置文件目录:/etc/sudoers.d/:在此目录下通过vim创建配置文件,效果和在/etc/sudoers文件中一样
给用户配置提权
配置格式:root ALL=(ALL) ALL
提权的用户 主机名=(提权到哪个用户) 提权的命令绝对路径
ALL 表示所有
多个用户名之间用,隔开(多个用户不指定用哪个则默认root)
多个主机名之间用,隔开
多个提权到指定用户之间用,隔开
多个命令之间用,隔开
# 进行sudo提权不要求验证密码
在配置中加上 NOPASSWD:,如:
zhangsan rhel9=(ALL) NOPASSWD:ALL(或具体命令)
zhangsan ALL=(root) NOPASSWD: /usr/bin/systemctl, /usr/bin/journalctl给zhangsan用户配置一个sudo提权,让zhangsan用户可以使用useradd命令创建用户:
zhangsan rhel9.example.com=(root) /usr/sbin/useradd
用户 主机 root用户 useradd命令
给memeda用户配置一个sudo提权,让memeda用户可以使用userdel命令删除用户:
memeda ALL=(root) /usr/sbin/userdel
一些无法被sudo使用的命令:
典型的例子:如果执行sudo cd会产生报错
在 Linux 中,命令分为两类:
外部程序(如 ls, vim):它们是硬盘上的一个文件,运行的时候会产生一个子进程。
内置命令(如 cd, umask, alias):它们不是独立程序,而是 Shell 解释器代码的一部分。
cd是且只能是内置的命令,因为“当前工作目录”(PWD)是进程的一个属性。一个进程只能修改自己的目录,不能修改父进程的目录。如果 cd 是个外部程序,它运行完(换完目录)就结束了,对原本的 Shell 没有任何影响,也就不可能切换到我们想去的目录。
当输入 sudo cd /root 时:
当前 Shell 发现你要运行 sudo(这是一个外部程序 /usr/bin/sudo)。
当前 Shell 克隆了一个 子进程来运行 sudo。
sudo 进程 获得了 root 权限,然后它尝试去运行你交给它的命令 cd。
sudo 发现硬盘上根本没有一个叫 /bin/cd 的程序(因为 cd 是 Shell 的内置功能),报错。
sudo: cd: command not found哪怕真的能执行成功,在我们所操控的当前shell视角里,什么也没发生。
给用户组配置提权
在 Linux 系统安装过程中,当你创建一个普通用户并勾选“成为管理员”或类似选项时,系统背后的实际操作就是将这个用户添加到一个具有 sudo 权限的特定用户组中。
配置格式:
%用户组 主机名=(提权到哪个用户)提权的命令%sudo ALL=(ALL:ALL) NOPASSWD:ALL
不论是配置用户提权还是用户组提权,目标身份如果不是root而是all,就可以使用sudo -u指定任意用户,sudo -g指定任意用户组身份,(ALL:ALL) 中第一个 ALL 代表可以 以任意用户身份运行,第二个ALL代表可以以任意用户组身份运行。
为了简化配置文件的内容使用sudo的别名(alias)写法:
依旧是:用户名、主机名、提权的用户名、执行的命令四个要素
例如:配置一个sudo提权,用户zhangsan lisi wangwu,可以在主机node1 node2 node3节点上提权到root user1 user2 身份,执行的命令 /usr/bin/touch、/usr/sbin/useradd
在配置文件中:
用户别名 User_Alias USERNUM=zhangsan,lisi,wangwu
主机别名 Host_Alias HOSTNUM=node1,node2,node3
提权到指定用户别名 Runas_Alias USEREXEC=root,user1,user2
执行命令的别名 Cmnd_Alias CMDNUM=/usr/bin/touch,/usr/sbin/useradd
(cmnd指的就是cmd)
【最后一行引用前面内容使之生效】USERNUM HOSTNUM=(USEREXEC) NOPASSWD:CMDNUM
eg:
User_Alias USERNUM=zhangsan
Host_Alias HOSTNUM = ALL
Runas_Alias USEREXEC = root
Cmnd_Alias CMDNUM = /usr/bin/touch
USERNUM HOSTNUM=(USEREXEC) NOPASSWD:CMDNUM
# 注意主机名等必须真实存在,或直接写ALL,别名必须大写visudo 和 sudoedit
sudoedit(等同于执行 sudo -e)本质上是提供给普通用户的一种受限提权编辑方式,用户先编辑一个副本文件,然后才会写入源文件。当 sudoedit 检测到正在编辑的文件是 /etc/sudoers(或相关的 sudo 配置文件夹)时,它会自动调用与 visudo 相同的内部校验引擎。而 visudo 的核心使命就是编辑 /etc/sudoers 文件并检查报错。
假设文件的101行第33列有语法错误:
sudoedit

visudo
