Chapter 05

用户、组与权限系统

掌握 Linux 权限模型的核心:rwx 三元组、数字权限、特殊位与 sudo 提权

Linux 权限模型概述

三类主体 × 三种权限

Linux 的权限系统基于一个简洁却强大的模型:每个文件/目录都有一个所有者(owner)和所属组(group),权限被分为三个维度(所有者、所属组、其他人),每个维度各有三种权限(读 r、写 w、执行 x)。

ls -l 输出解析 ───────────────────────────────────────────────────────────── - rwx r-x r-- 2 alice developers 4096 Jan 10 file.sh │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ 文件大小 │ │ │ │ │ │ └─ 所属组 │ │ │ │ │ └─ 所有者 │ │ │ │ └─ 硬链接数 │ │ │ └─ 其他人权限 (o: others) │ │ └─ 所属组权限 (g: group) │ └─ 所有者权限 (u: user/owner) └─ 文件类型 (- 普通 d 目录 l 链接 c 字符设备 b 块设备)─────────────────────────────────────────────────────────────

三种权限的含义

r(读,Read = 4)
对文件:可以读取文件内容(cat、less、cp 的源文件)。对目录:可以列出目录中的文件名(ls),但不能进入目录或读取文件详细信息。
w(写,Write = 2)
对文件:可以修改、截断或覆盖文件内容。对目录:可以在目录中创建、删除、重命名文件(注意:删除文件由目录的 w 权限控制,而非文件自身的 w 权限)。
x(执行,Execute = 1)
对文件:可以将文件作为程序执行(shell 脚本、二进制程序)。对目录:可以进入(cd)该目录并访问其中的文件——这是"目录权限的关键位",没有 x 权限即使有 r 也无法进入目录。

查看权限:ls -l

# 详细列表(显示权限、所有者、大小、时间)
ls -l
ls -la          # 包含隐藏文件(.开头)
ls -lh          # 人类可读大小(KB/MB/GB)
ls -ln          # 显示 UID/GID 数字而非用户名

# 查看特定文件的权限
ls -l /etc/passwd
ls -ld /etc             # -d 查看目录本身而非目录内容
stat /etc/passwd        # 显示完整的 inode 信息包括权限

# 输出示例
# -rw-r--r-- 1 root root 2847 Jan  1 10:00 /etc/passwd
# drwxr-xr-x 3 alice devs 4096 Jan  1 10:00 /home/alice
# lrwxrwxrwx 1 root root    7 Jan  1 10:00 /bin -> usr/bin

chmod:修改权限

符号模式(推荐用于理解)

# 语法:chmod [ugoa][+-=][rwx] 文件
# u=user(owner), g=group, o=others, a=all

chmod u+x script.sh         # 给所有者添加执行权限
chmod g-w config.conf       # 移除所属组的写权限
chmod o=r public.txt        # 设置其他人权限为只读
chmod a+r announcement.txt  # 所有人添加读权限
chmod u+x,g+x deploy.sh     # 同时修改多个
chmod a-x somefile          # 去掉所有人的执行权限

# 对目录递归修改
chmod -R 755 /var/www/html  # 递归修改整个目录树

数字模式(高效简洁)

将 rwx 视为二进制位:r=4, w=2, x=1,三个数字分别表示 owner/group/others。

数字二进制权限典型用途
7111rwx目录所有者
6110rw-普通文件所有者
5101r-x目录组/其他人
4100r--只读文件
0000---无任何权限
# 常用数字权限组合
chmod 755 script.sh      # rwxr-xr-x:可执行脚本
chmod 644 config.txt     # rw-r--r--:普通文本文件
chmod 600 ~/.ssh/id_rsa  # rw-------:私钥(严格保密)
chmod 700 ~/.ssh         # rwx------:SSH 目录
chmod 777 /tmp/shared    # rwxrwxrwx:所有人可读写执行(谨慎)
chmod 640 /etc/app.conf  # rw-r-----:配置文件,组可读

# 查看数字权限
stat -c "%a %n" /etc/passwd     # 输出: 644 /etc/passwd
stat -c "%a %n" /usr/bin/passwd # 输出: 4755(SUID 位设置)
权限设置黄金法则

chown 与 chgrp:修改所有者

# chown:修改文件所有者
chown alice file.txt            # 修改所有者为 alice
chown alice:developers file.txt # 同时修改所有者和所属组
chown :developers file.txt      # 只修改所属组(等同 chgrp)
chown -R www-data /var/www      # 递归修改目录树

# chgrp:修改所属组
chgrp developers project/       # 修改目录所属组
chgrp -R docker /var/docker     # 递归修改

# 查看当前用户信息
whoami          # 当前用户名
id              # uid=1000(alice) gid=1000(alice) groups=1000(alice),27(sudo),1001(docker)
id alice        # 查看 alice 的 uid/gid/groups
groups          # 当前用户所在的所有组

用户与组管理

用户管理命令

# 创建用户
useradd alice                          # 创建用户(不创建主目录)
useradd -m -s /bin/bash alice          # 创建主目录,指定 shell
useradd -m -G sudo,docker alice        # 加入附加组

# 设置/修改密码
passwd alice            # 为 alice 设置密码(需要 root)
passwd                  # 修改当前用户密码

# 修改用户
usermod -aG docker alice  # 将 alice 加入 docker 组(-a 追加)
usermod -s /bin/zsh alice # 修改默认 shell
usermod -l newname alice  # 改用户名

# 删除用户
userdel alice           # 删除用户(保留主目录)
userdel -r alice        # 删除用户及其主目录

# 创建/删除组
groupadd developers
groupdel developers

# 查看用户信息文件
cat /etc/passwd         # 用户信息(用户名:密码占位:UID:GID:注释:主目录:Shell)
cat /etc/group          # 组信息(组名:密码:GID:成员列表)
cat /etc/shadow         # 加密密码(只有 root 可读)

SUID、SGID 与 Sticky Bit

三种特殊权限位

SUID(Set User ID,数字 4)
设置在可执行文件上。任何用户执行该程序时,进程以文件所有者的身份运行。最典型的例子是 /usr/bin/passwd——普通用户执行 passwd 命令时,进程以 root 身份运行,因此可以修改 /etc/shadow。ls -l 显示为 -rwsr-xr-x(s 替代 x)。
SGID(Set Group ID,数字 2)
设置在可执行文件上时:进程以文件所属组的身份运行。设置在目录上时:在该目录中创建的新文件/目录会继承该目录的所属组(而不是创建者的默认组)。团队协作目录通常设置此位。ls -l 显示为 drwxr-sr-x(s 替代 g 的 x)。
Sticky Bit(粘滞位,数字 1)
设置在目录上。防止用户删除不属于自己的文件,即使该用户对目录有写权限。/tmp 目录就使用了粘滞位:所有用户都可以创建文件,但只能删除自己的文件。ls -l 显示为 drwxrwxrwt(t 替代 o 的 x)。
# 查看特殊位
ls -l /usr/bin/passwd    # -rwsr-xr-x(SUID)
ls -l /usr/bin/wall      # -rwxr-sr-x(SGID)
ls -ld /tmp              # drwxrwxrwt(Sticky Bit)

# 设置特殊位(符号方式)
chmod u+s /usr/local/bin/myapp   # 设置 SUID
chmod g+s /home/team/project     # 设置 SGID(目录)
chmod +t /tmp/shared             # 设置 Sticky Bit

# 设置特殊位(数字方式,第4位)
chmod 4755 myapp      # 4 = SUID(rwsr-xr-x)
chmod 2775 teamdir    # 2 = SGID(rwxrwsr-x)
chmod 1777 /tmp       # 1 = Sticky(rwxrwxrwt)
chmod 6755 special    # 6 = SUID + SGID

# 查找系统中所有 SUID 文件(安全审计)
find / -perm -4000 -type f 2>/dev/null
find / -perm -2000 -type f 2>/dev/null   # SGID 文件
SUID 安全风险

SUID 程序以 root 身份运行,如果存在安全漏洞(缓冲区溢出、路径注入等),攻击者可以借此获得 root 权限。定期审计 SUID/SGID 文件,删除不必要的特殊位。永远不要为 Shell(bash、sh)或文本编辑器设置 SUID。

sudo:临时提权

sudo 的工作原理

sudo(Substitute User DO)允许授权用户以其他用户(通常是 root)的身份执行特定命令,而无需知道 root 密码。sudo 权限由 /etc/sudoers 文件控制。

# 基本用法
sudo command                # 以 root 身份执行命令
sudo -u alice command       # 以 alice 身份执行
sudo -i                     # 启动 root 登录 shell(获取 root 环境变量)
sudo -s                     # 启动 root shell(保留当前环境变量)
sudo -l                     # 列出当前用户可以 sudo 的命令
sudo !!                     # 以 sudo 重新执行上一条命令(bash 技巧)

# 常用 sudo 操作
sudo apt update
sudo systemctl restart nginx
sudo nano /etc/hosts
sudo chmod 600 /etc/ssl/private/key.pem

# 切换到 root(不推荐长期使用)
su -              # 完全切换到 root(需要 root 密码)
su - alice        # 切换到 alice(需要 alice 密码)
exit              # 退出 su/sudo -i 会话

配置 /etc/sudoers

务必使用 visudo 编辑

永远不要直接用文本编辑器编辑 /etc/sudoers,语法错误会导致所有用户(包括 root)都无法使用 sudo,造成系统锁定。使用 visudo 命令,它会在保存前验证语法。

# 使用 visudo 编辑(会进行语法检查)
visudo
visudo -f /etc/sudoers.d/alice   # 编辑单独的 drop-in 文件(推荐)

# /etc/sudoers 语法格式:
# 用户/组  主机=(执行身份)  命令

# 常用配置示例
alice   ALL=(ALL:ALL) ALL           # alice 可以在所有主机以任意用户身份执行任意命令
%sudo   ALL=(ALL:ALL) ALL           # sudo 组成员(% 表示组)
%wheel  ALL=(ALL) ALL               # wheel 组(Red Hat 系惯例)

# 无密码 sudo(CI/CD 常用)
alice   ALL=(ALL) NOPASSWD:ALL
deploy  ALL=(ALL) NOPASSWD:/usr/bin/systemctl,/usr/bin/docker

# 限制只能 sudo 特定命令
bob     ALL=(root) /usr/bin/apt,/usr/bin/systemctl restart nginx

# 将用户加入 sudo 组(Ubuntu)
usermod -aG sudo alice
# 将用户加入 wheel 组(CentOS/RHEL)
usermod -aG wheel alice

umask:默认权限掩码

新建文件的默认权限

umask 定义了创建新文件/目录时要去掉的权限位。系统默认权限:文件为 666(rw-rw-rw-),目录为 777(rwxrwxrwx)。用默认权限减去 umask 得到实际权限。

# 查看当前 umask
umask           # 0022(八进制)
umask -S        # u=rwx,g=rx,o=rx(符号形式)

# umask 计算示例:
# 文件默认 666,umask 022 → 666-022 = 644(rw-r--r--)
# 目录默认 777,umask 022 → 777-022 = 755(rwxr-xr-x)

# 临时修改 umask(当前会话有效)
umask 027       # 文件→640,目录→750(组可读,其他人无权限)
umask 077       # 文件→600,目录→700(只有所有者可访问)

# 永久修改 umask(写入配置文件)
echo "umask 022" >> ~/.bashrc     # 用户级
echo "umask 022" >> /etc/profile  # 系统级(需要 root)
umask 值文件权限目录权限适用场景
022644(rw-r--r--)755(rwxr-xr-x)默认值,公共服务器
027640(rw-r-----)750(rwxr-x---)企业服务器,增强安全
077600(rw-------)700(rwx------)高安全,只有所有者访问
002664(rw-rw-r--)775(rwxrwxr-x)团队协作,组内共享

访问控制列表(ACL)

突破三类主体限制

传统的 rwx 权限只能针对所有者、所属组、其他人三类主体设置。ACL(Access Control List)允许为特定用户或组单独设置权限,解决更复杂的权限需求。

# 安装 ACL 工具(通常已预装)
apt install acl    # Debian/Ubuntu

# 查看文件的 ACL
getfacl file.txt
# 输出示例:
# file: file.txt
# owner: alice
# group: developers
# user::rw-
# user:bob:r--   ← 专门给 bob 设置的读权限
# group::r--
# mask::r--
# other::---

# 设置 ACL
setfacl -m u:bob:r-- file.txt        # 给 bob 添加读权限
setfacl -m g:ops:rwx /deploy/        # 给 ops 组添加完全权限
setfacl -m u:bob:--- secret.txt      # 禁止 bob 访问
setfacl -R -m u:bob:rx /var/www/     # 递归设置

# 设置默认 ACL(新建文件继承)
setfacl -d -m g:developers:rwx /project/

# 删除 ACL
setfacl -x u:bob file.txt    # 删除 bob 的 ACL 条目
setfacl -b file.txt          # 删除所有 ACL 条目

实战:Web 服务器权限配置

# 场景:Nginx 服务器,开发者需要上传文件,www-data 需要读取

# 1. 设置 Web 根目录所有者
chown -R www-data:www-data /var/www/html

# 2. 设置目录权限:755(进入+列出)
find /var/www/html -type d -exec chmod 755 {} \;

# 3. 设置文件权限:644(读取)
find /var/www/html -type f -exec chmod 644 {} \;

# 4. 允许 alice 上传文件(ACL 方式,不修改所有者)
setfacl -R -m u:alice:rwx /var/www/html
setfacl -d -m u:alice:rwx /var/www/html    # 新建文件继承

# 5. 上传目录设置 SGID(新文件继承 www-data 组)
chmod g+s /var/www/html/uploads

# 验证设置
ls -la /var/www/html
getfacl /var/www/html
权限问题排查步骤
  1. 确认操作用户:whoamiid
  2. 查看文件权限:ls -la 文件
  3. 查看目录链上的权限(从根到文件的每一级目录都需要 x 权限)
  4. 检查 ACL:getfacl 文件
  5. 以 root 测试:sudo cat 文件(确认是权限问题还是文件损坏)
  6. SELinux/AppArmor(若启用):getenforceaa-status
本章小结

Linux 权限系统的核心要点:① 权限分三类主体(所有者/组/其他人)× 三种权限(r/w/x),数字表示法 755/644 是最常用的设定;② 目录的 x 权限是进入的关键,没有 x 则 r 也无法使用;③ 删除文件由目录的 w 权限控制而非文件自身;④ SUID 让程序以所有者身份运行(passwd 命令的基础),SGID 让目录中新文件继承组,Sticky Bit 防止用户删除他人文件(/tmp 的保护机制);⑤ umask 控制新建文件的默认权限(022 → 文件 644,目录 755);⑥ ACL 突破三类主体限制,为特定用户精细授权;⑦ 务必用 visudo 编辑 sudoers,语法错误会锁定系统。