🐧 Linux 用户管理与文件权限深度解析
在 Linux 系统中,用户和组管理与文件权限控制是系统管理的两大基石。无论你是刚入门的运维新人,还是准备 RHCSA 认证的考生,理解这两块内容都能让你在 Linux 世界中游刃有余。本文将为你系统性地梳理账户管理、工作组机制、文件权限体系以及高级权限控制等内容。
一、账户与工作组分类
1.1 用户的三类角色
Linux 是一个真正意义上的多用户、多任务操作系统,它将用户划分为三个层次:
| 用户类型 | 说明 | 特点 |
|---|---|---|
| 超级用户(root) | 系统最高权限拥有者 | 拥有一切权限,建议仅在必要时使用 |
| 系统用户 | 系统进程所需的账户 | 如 bin、daemon、sshd 等,不能登录系统 |
| 普通用户 | 日常使用系统的账户 | 权限受限,只能操作自己有权访问的资源 |
1.2 工作组的两种类型
| 类型 | 说明 |
|---|---|
| 基本组(私有组) | 新建用户时,若未指定所属组,系统会自动创建与用户名同名的组 |
| 扩展组(公有组) | 可容纳多个用户,组内成员共享该组所拥有的权限 |
二、核心配置文件详解
用户和组的信息存储在四个关键文件中:
| 文件 | 功能 | 权限说明 |
|---|---|---|
/etc/passwd | 用户账号信息 | 所有用户可读 |
/etc/shadow | 用户密码密文 | 仅 root 可读 |
/etc/group | 工作组信息 | 所有用户可读 |
/etc/gshadow | 工作组密码 | 仅 root 可读 |
2.1/etc/passwd— 用户账号文件
每一行代表一个用户,共 7 个字段,用:分隔:
root:x:0:0:root:/root:/bin/bash字段含义依次为:用户名:密码占位符:UID:GID:注释信息:家目录:登录Shell
🔑UID 规则:root 为 0,系统用户为 1~999,普通用户从 1000 开始连续编号。
2.2/etc/shadow— 影子密码文件
存储加密后的密码,权限为----------(仅有 root 可读写):
root:$6$u6dOBCaz...Ndv/::0:99999:7:::9 个字段依次为:登录名:加密口令:最后修改时间:最小间隔:最大间隔:警告时间:不活动时间:失效时间:标志
2.3/etc/group— 工作组文件
root:x:0:字段含义:组名:组密码:GID:组成员列表
三、用户管理实战
3.1 创建用户
# 基本创建useraddzzz# 指定 UID、Shell、过期时间useradd-u2001-s/bin/bash-e-1sss# 禁止登录、不创建家目录(常用于 FTP 等服务账户)useradd-M-s/sbin/nologin zzz_srv# 指定家目录、基本组useraddsss_dev-u3001-gzzz-d/test创建用户后,系统会自动完成以下操作:
- 在
/etc/passwd、/etc/shadow、/etc/group中添加记录 - 创建家目录(默认
/home/用户名) - 复制
/etc/skel/下的模板文件到新家目录
3.2 修改用户信息
# 修改用户名并锁定账户usermodzzz-lZZZ-L# 修改家目录usermodsss-d/home/sss3.3 设置与修改密码
# 交互式设置passwdzzz# 非交互式设置(脚本中常用)echo"123456"|passwd--stdinsss# 锁定/解锁账户passwd-lzzz# 锁定passwd-uzzz# 解锁3.4 删除用户
# -r 参数会一并删除家目录和邮件池userdel-rzzz3.5 用户切换
suzzz# 切换用户,但不加载目标用户的环境变量su- zzz# 切换用户,同时加载完整的环境变量💡关键区别:
su -会重新加载目标用户的.bash_profile、.bashrc等配置文件,相当于"重新登录";而su仅切换身份,保留当前的环境变量。
四、工作组管理
4.1 创建与修改工作组
# 创建工作组groupaddgroup1# 指定 GID 创建groupaddgroup2-g2000# 修改组名和 GIDgroupmod-g3000-ngroup11 group14.2 组成员管理
# 添加成员到组gpasswd-azzz group2# 批量添加gpasswd-Mzzz,sss ZZgroup# 指派组管理员gpasswd-Azzz group2# 从组中移除成员gpasswd-dzzz group24.3 修改文件所属组
五、sudo 提权机制
5.1 什么是 sudo?
sudo(Super User DO)允许普通用户以超级用户(或其他用户)的身份执行命令,而无需知道 root 密码。它通过/etc/sudoers文件进行精细的权限控制。
5.2 sudo 执行流程
- 用户执行
sudo 命令,系统要求输入用户自己的密码(root 执行 sudo 时无需密码) - 验证成功后,系统检查
/etc/sudoers中该用户是否有执行权限 - 若授权通过,则以指定身份执行命令
5.3 配置 sudoers
使用visudo或vim /etc/sudoers编辑:
rootALL=(ALL)ALL# 用户名 主机名=(可切换的身份) 可执行的命令为普通用户授权:
zzzALL=(ALL)ALL配置完成后,zzz 用户就可以使用 sudo 执行管理员命令了:
5.4 ⭐ 深入理解 sudo 的提权机制(重点)
sudo 只能对命令的"子 shell"提权
很多初学者会误以为sudo像su一样切换了用户身份,然后后续所有命令都以 root 身份执行。这是一个常见的误解!
实际上,sudo的工作机制是:
sudo仅为紧随其后的那条命令创建一个子进程(子 shell),在这个子进程中以 root 身份执行该命令。命令执行完毕后,子进程退出,当前 shell 依然是普通用户身份。
这就引出了一个经典问题:为什么sudo cd /root会失败?
sudo cd /root失败的原因分析
[zzz@server ~]$sudocd/root[sudo]zzz 的密码: sudo: cd: 未找到命令# 或者:命令执行后没有任何效果失败原因有两点:
原因一:cd是 Shell 内置命令,不是外部程序
sudo只能执行外部程序(即有独立二进制文件的命令),而cd是 shell 自身实现的内置命令(built-in),它不存在/bin/cd这样的可执行文件。sudo无法找到一个叫cd的外部程序来以 root 身份执行。
原因二:即使能执行,也只影响子 shell 的工作目录
退一步说,即便cd有外部可执行文件,sudo cd /root的执行效果是:
sudo创建一个子进程- 子进程的目录切换到了
/root - 子进程立即退出,目录变更随之消失
- 当前父 shell 的目录完全没有改变
💡一句话总结:
sudo只为命令开了一个"特权小窗口"(子进程),窗口关闭后特权就消失了。像cd这种改变 shell 状态的命令,在子窗口中执行毫无意义。
sudo 提权的工作原理图
┌─────────────────────────────────────────────────────────┐ │ 当前 Shell(zzz) │ │ ┌──────────────────────────────────────────────────┐ │ │ │ $ whoami → zzz │ │ │ │ $ sudo whoami → root (子进程提权) │ │ │ │ $ whoami → zzz (子进程已退出) │ │ │ │ $ sudo cd /root → ❌ (cd无外部程序 / 子shell │ │ │ │ 退出后目录恢复原样) │ │ │ └──────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────┘5.5 ⭐ 获取真正的提权子 shell:sudo -i / sudo -s
理解了上述原理后,我们就知道:如果需要连续执行多条管理命令,每次敲sudo前缀效率很低。正确的做法是获取一个持续的提权子 shell。
# 方法一:获取 root 登录 shell(推荐)sudo-i# 方法二:用 root 身份运行当前 shellsudo-s# 在提权子 shell 中连续执行多条命令[zzz@server ~]$sudo-i[root@server ~]# useradd newuser[root@server ~]# passwd newuser[root@server ~]# groupadd newgroup[root@server ~]# ls /root[root@server ~]# exit # 退出子 shell,回到普通用户[zzz@server ~]$# 又变回普通用户了
sudo -ivssudo -s:
sudo -i:模拟登录,会加载 root 的完整环境变量(相当于sudo su -),推荐使用sudo -s:仅切换身份,保留当前 shell 环境(相当于sudo su)
使用sudo -i后,当前 shell 会成为一个持久的提权子 shell,所有命令都直接以 root 身份执行,不再需要重复输入sudo,直到你输入exit退出。
六、文件权限体系
6.1 查看文件权限
使用ll或ls -l命令查看文件的详细信息:
输出示例:
-rwxr-xr-x. 1 root root 143368 Apr 27 2020 /usr/bin/ls从左侧起第一个字符表示文件类型,后面 9 个字符分为三组,表示三类用户的权限:
| 位置 | 含义 |
|---|---|
| 第1位 | 文件类型(-普通文件、d目录、l软链接等) |
| 第2-4位 | 所有者(owner/u)权限 |
| 第5-7位 | 所属组(group/g)权限 |
| 第8-10位 | 其他人(other/o)权限 |
6.2 权限的字符与数字表示
| 权限 | 字符 | 二进制 | 数字 |
|---|---|---|---|
| 无权限 | --- | 000 | 0 |
| 仅执行 | --x | 001 | 1 |
| 仅写入 | -w- | 010 | 2 |
| 写入+执行 | -wx | 011 | 3 |
| 仅读取 | r-- | 100 | 4 |
| 读取+执行 | r-x | 101 | 5 |
| 读取+写入 | rw- | 110 | 6 |
| 全部权限 | rwx | 111 | 7 |
6.3 文件与目录的权限含义对比
| 权限 | 对文件的影响 | 对目录的影响 |
|---|---|---|
| r(读) | 可读取文件内容 | 可列出目录内容(文件名) |
| w(写) | 可修改文件内容 | 可创建/删除目录中的文件(需与x配合) |
| x(执行) | 可作为脚本/程序执行 | 可进入目录(如cd) |
⚠️注意:文件权限通常出现
---、r--、r-x、rw-、rwx;目录权限通常出现---、r-x、rwx。目录的 w 权限必须配合 x 权限才能生效(才能创建或删除文件)。
七、🌟 父目录权限 vs 文件自身权限(核心解析)
这是一个非常容易混淆但又极为重要的知识点:
问题:对于目录下的文件,用户的访问到底受父目录权限限制,还是受文件自身权限限制?
答案是:两者都限制,但作用不同。
7.1 访问文件内容时
当用户要读取或写入一个文件的内容时,需要同时满足两个条件:
- 对父目录有 x 权限——才能"穿过"目录到达该文件
- 对文件本身有 r/w 权限——才能读取/修改文件内容
例:用户 zzz 访问 /home/zzz/secret.txt 需要: - / → 任何人都有 r-x 权限 ✅ - /home → zzz 需要 x 权限 ✅ - /home/zzz → zzz 作为所有者,有 rwx 权限 ✅ - secret.txt → zzz 需要 r 权限才能读取 ✅7.2 创建/删除文件时
当用户要在目录中创建或删除文件时,起决定作用的是父目录的权限,而不是文件自身的权限!
例:用户 A 在 /shared 目录下创建了一个文件 file.txt - /shared 权限为 rwxrwxrwx(任何人可读写执行) - file.txt 权限为 rw-------(仅 A 可读写) 此时用户 B 能否删除 file.txt? ✅ 能!因为 B 对父目录 /shared 有 w 和 x 权限 ❌ 但 B 不能读取 file.txt 的内容(受文件自身 r 权限限制)7.3 总结对照表
| 操作 | 受父目录权限影响 | 受文件自身权限影响 | 关键权限 |
|---|---|---|---|
| 进入目录 | ✅ | — | 父目录 x |
| 列出目录内容 | ✅ | — | 父目录 r |
| 读取文件内容 | ✅ | ✅ | 父目录 x + 文件 r |
| 修改文件内容 | ✅ | ✅ | 父目录 x + 文件 w |
| 删除/重命名文件 | ✅ | ❌ | 父目录 wx |
| 在目录中创建文件 | ✅ | — | 父目录 wx |
💡关键结论:对文件内容读写的控制 = 父目录的 x 权限 + 文件自身的 r/w 权限;对文件创建/删除的控制 ≈ 父目录的 wx 权限(文件自身的权限对此无效)。这就是粘滞位(Sticky Bit)存在的原因——防止用户随意删除他人的文件。
八、修改权限与归属
8.1 chmod — 修改权限
# 字符模式chmodu+xfile# 给所有者添加执行权限chmodg-wfile# 移除所属组的写权限chmodo=rfile# 将其他人的权限设为只读chmoda+xfile# 给所有用户添加执行权限# 数字模式chmod755file# rwxr-xr-xchmod644file# rw-r--r--chmod700file# rwx------# 递归设置目录权限chmod-R755/path/to/dir8.2 chown — 修改所有者与所属组
# 仅修改所有者chownzzzfile# 同时修改所有者和所属组chownzzz:zzzfile# 仅修改所属组chown:group1file# 递归修改chown-Rzzz:zzz /path/to/dir九、特殊权限详解
9.1 SUID(Set UID)
作用:当可执行程序设置了 SUID 权限后,普通用户在执行该程序期间,暂时获得程序文件所有者的权限。
典型例子:/usr/bin/passwd
[root@server ~]# ll /usr/bin/passwd-rwsr-xr-x.1root root326488月102021/usr/bin/passwd普通用户修改密码时,需要写入只有 root 能访问的/etc/shadow文件。正是因为passwd命令设置了 SUID(所有者权限位上的s),普通用户在执行它时暂时获得了 root 身份,才能成功修改密码。
注意:
- ✅ 仅对二进制程序有效
- ✅ 仅在程序执行期间生效
- ❌ 对脚本文件无效
9.2 SGID(Set GID)
对文件:执行者暂时获得文件所属组的权限。
对目录:在该目录下新建的文件或子目录,其所属组自动继承父目录的所属组。
9.3 Sticky Bit(粘滞位)
作用:仅对目录有效。设置了 Sticky Bit 的目录中,用户只能删除自己创建的文件,即使他对该目录有 w 权限,也无法删除别人的文件。
典型例子:/tmp目录
[root@server ~]# ll -d /tmpdrwxrwxrwt.10root root4096Jul1010:00 /tmp权限位上的t就是 Sticky Bit 标志。
9.4 设置特殊权限
# 字符模式chmodu+sfile# 设置 SUIDchmodg+sfile# 设置 SGIDchmodo+tdir# 设置 Sticky Bit# 数字模式(4位数字)chmod4777file# SUID + rwxrwxrwxchmod2777file# SGID + rwxrwxrwxchmod1777dir# Sticky Bit + rwxrwxrwx| 首位数字 | 含义 |
|---|---|
| 0 | 不设置特殊权限 |
| 1 | 仅 Sticky Bit |
| 2 | 仅 SGID |
| 3 | SGID + Sticky Bit |
| 4 | 仅 SUID |
| 5 | SUID + Sticky Bit |
| 6 | SUID + SGID |
| 7 | 全部三种特殊权限 |
十、ACL 访问控制列表
当传统的 UGO 权限模型无法满足精细化权限管理需求时,ACL(Access Control List)就派上用场了。
10.1 查看 ACL
getfacl /project10.2 设置 ACL
# 给指定用户分配权限setfacl-mu:sss:rx /project# 给指定组分配权限setfacl-mg:group1:rwx /project# 递归设置setfacl-R-mu:sss:rx /project# 设置默认权限(新文件自动继承)setfacl-d-mu:sss:rx /project10.3 删除 ACL
# 删除指定用户的 ACLsetfacl-xu:sss /project# 删除所有 ACLsetfacl-b/project💡 设置了 ACL 的文件/目录,在
ls -l输出中权限位后会多一个+号标记。
十一、umask 权限掩码
11.1 概念
umask决定了新建文件和目录时的默认权限。系统从完整权限中"扣除" umask 值,得到默认权限:
文件默认权限 = 0666 - umask 目录默认权限 = 0777 - umask11.2 查看与修改
# 查看当前 umask[root@server ~]# umask0022# 新建文件/目录的默认权限[root@server ~]# touch file1 # 0666 - 0022 = 0644 = rw-r--r--[root@server ~]# mkdir dir1 # 0777 - 0022 = 0755 = rwxr-xr-x# 临时修改 umask[root@server ~]# umask 000[root@server ~]# touch file2 # 0666 - 0000 = 0666 = rw-rw-rw-💡注意:umask 的修改仅对当前 shell 会话有效。若要永久修改,需要写入
/etc/profile或~/.bashrc。
十二、查看用户登录信息
| 命令 | 功能 | 读取文件 |
|---|---|---|
users | 查看当前登录的用户 | — |
who | 显示登录用户及详细信息 | /var/run/utmp |
w | 显示登录用户及当前活动 | — |
last | 查看历史登录记录 | /var/log/wtmp |
lastlog | 查看每个用户最近登录时间 | /var/log/lastlog |
[root@server ~]# whoroot pts/02023-05-0614:36(192.168.48.1)[root@server ~]# last -3root pts/0192.168.48.1 Sat May614:36 still loggedinzzz tty2 tty2 Sat May614:26 -14:33(00:07)root pts/2192.168.48.1 Sat May610:51 -14:34(03:43)[root@server ~]# lastlogUsername Port From Latest root pts/0192.168.48.1 六5月614:36:03 +08002023bin **从未登录过**