用户与权限管理
问题
请详细介绍 Linux 的用户管理和权限体系,包括 UGO 模型、特殊权限、ACL 和 sudo。
答案
用户与组
Linux 是多用户系统,每个用户有唯一的 UID,归属一个或多个组(GID)。
# 用户信息存储在 /etc/passwd
# 格式:用户名:密码占位:UID:GID:描述:主目录:登录Shell
root:x:0:0:root:/root:/bin/bash
nginx:x:998:996:nginx user:/var/cache/nginx:/sbin/nologin
# 密码哈希存储在 /etc/shadow(仅 root 可读)
# 组信息存储在 /etc/group
用户管理命令
# 创建用户
useradd -m -s /bin/bash -G docker,sudo username
# -m: 创建主目录 -s: 指定 Shell -G: 附加组
# 修改用户
usermod -aG docker username # 将用户加入 docker 组(-a 表示追加)
usermod -s /sbin/nologin nginx # 禁止登录
# 删除用户
userdel -r username # -r: 同时删除主目录
# 设置密码
passwd username
# 切换用户
su - username # - 加载目标用户的环境变量
sudo -u username command # 以指定用户身份执行命令
# 查看用户信息
id username # uid, gid, groups
whoami # 当前用户
w # 当前登录用户
last # 登录历史
文件权限(UGO 模型)
每个文件有三组权限:Owner(所有者)、Group(所属组)、Others(其他人)。
-rwxr-xr-- 1 root staff 4096 Mar 15 10:00 script.sh
│├─┤├─┤├─┤
│ │ │ │
│ │ │ └── Others: r-- (只读)
│ │ └────── Group: r-x (读+执行)
│ └────────── Owner: rwx (读+写+执行)
└──────────── 文件类型: - (普通文件)
权限数字表示
| 权限 | 字符 | 数字 |
|---|---|---|
| 读 | r | 4 |
| 写 | w | 2 |
| 执行 | x | 1 |
| 无 | - | 0 |
# chmod 修改权限
chmod 755 script.sh # rwxr-xr-x
chmod 644 config.yml # rw-r--r--
chmod 600 id_rsa # rw------- (SSH 私钥必须 600)
# 符号方式
chmod u+x script.sh # 给 Owner 加执行权限
chmod g-w file.txt # 去掉 Group 的写权限
chmod o= file.txt # Others 无任何权限
chmod a+r file.txt # 所有人加读权限
# chown 修改所有者
chown nginx:nginx /var/www/html -R
chown :docker /var/run/docker.sock
# chgrp 修改所属组
chgrp staff project/
目录权限的特殊含义
目录的 rwx 含义与文件不同
| 权限 | 对文件的含义 | 对目录的含义 |
|---|---|---|
| r | 读取文件内容 | 列出目录内容(ls) |
| w | 修改文件内容 | 在目录中创建/删除文件 |
| x | 执行文件 | 进入目录(cd) |
一个常见陷阱:目录有 r 但没有 x,可以 ls 看到文件名但无法读取文件内容。
特殊权限
除了基本的 rwx,还有三种特殊权限位:
| 权限 | 数字 | 对文件 | 对目录 |
|---|---|---|---|
| SUID | 4 | 以文件所有者身份执行 | 无意义 |
| SGID | 2 | 以文件所属组身份执行 | 新创建的文件继承目录的组 |
| Sticky | 1 | 无意义 | 只有文件所有者才能删除文件 |
# SUID 示例:passwd 命令需要修改 /etc/shadow(root 权限)
ls -l /usr/bin/passwd
# -rwsr-xr-x 1 root root # 注意 's' 替代了 Owner 的 'x'
# SGID 示例:共享目录,新文件自动继承组
chmod 2775 /shared/project
# drwxrwsr-x # 注意 Group 位的 's'
# Sticky Bit 示例:/tmp 目录,用户只能删自己的文件
ls -ld /tmp
# drwxrwxrwt # 注意 Others 位的 't'
# 设置特殊权限
chmod 4755 file # 设置 SUID
chmod 2775 dir # 设置 SGID
chmod 1777 dir # 设置 Sticky Bit
chmod u+s file # 符号方式设置 SUID
chmod g+s dir # 符号方式设置 SGID
chmod o+t dir # 符号方式设置 Sticky
SUID 安全风险
SUID 允许用户以文件所有者身份执行程序。如果一个 root 所有的 SUID 程序有漏洞,攻击者可以获取 root 权限。
# 安全审计:查找所有 SUID/SGID 文件
find / -perm -4000 -type f 2>/dev/null # SUID
find / -perm -2000 -type f 2>/dev/null # SGID
umask 默认权限
umask 决定新创建文件/目录的默认权限:
# 查看当前 umask
umask # 如:0022
# 计算方式(用掩码减去)
# 文件默认权限 = 666 - umask = 666 - 022 = 644 (rw-r--r--)
# 目录默认权限 = 777 - umask = 777 - 022 = 755 (rwxr-xr-x)
# 设置 umask
umask 027 # 文件: 640, 目录: 750
# 永久设置:写入 ~/.bashrc 或 /etc/profile
ACL 细粒度权限
传统 UGO 模型只能为一个 Owner 和一个 Group 设置权限。ACL(Access Control List)允许为任意用户或组设置权限:
# 查看 ACL
getfacl /data/project
# 为特定用户设置权限
setfacl -m u:alice:rwx /data/project
setfacl -m u:bob:r-x /data/project
# 为特定组设置权限
setfacl -m g:developers:rwx /data/project
# 设置默认 ACL(新文件自动继承)
setfacl -d -m u:alice:rwx /data/project
setfacl -d -m g:developers:rwx /data/project
# 删除 ACL
setfacl -x u:alice /data/project # 删除某用户的 ACL
setfacl -b /data/project # 删除所有 ACL
# 递归设置
setfacl -R -m g:developers:rwx /data/project
ACL 优先级
ACL 判断顺序:Owner → Named User ACL → Group/Named Group ACL → Others。文件具有 ACL 时,ls -l 权限位后会显示 + 号。
sudo 权限管理
sudo 是 Linux 权限提升的标准机制,比直接用 root 账号更安全、更可审计:
/etc/sudoers(使用 visudo 编辑)
# 用户权限格式:谁 在哪里=(以谁身份) 可以执行什么命令
# root 可以在任何主机以任何身份执行任何命令
root ALL=(ALL:ALL) ALL
# sudo 组的成员可以执行任何命令
%sudo ALL=(ALL:ALL) ALL
# 允许 deploy 用户免密执行特定命令
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx, \
/usr/bin/systemctl restart app
# 允许 dba 组执行数据库相关命令
%dba ALL=(ALL) NOPASSWD: /usr/bin/mysql, /usr/bin/mysqldump
# 命令别名(简化管理)
Cmnd_Alias NETWORKING = /sbin/route, /sbin/iptables, /sbin/ip
%netadmin ALL=(ALL) NOPASSWD: NETWORKING
sudoers 安全要点
- 始终使用
visudo编辑:会做语法检查,防止配置错误导致 sudo 不可用 - 最小权限原则:只授予必要的命令权限
- 避免
ALL=(ALL) NOPASSWD: ALL:这等于给了 root 权限 - sudoers.d 目录:推荐将配置放在
/etc/sudoers.d/下,便于管理
常见面试问题
Q1: chmod 755 和 chmod 644 分别是什么权限?
答案:
755=rwxr-xr-x:Owner 读写执行,Group 和 Others 读和执行。用于可执行文件和目录644=rw-r--r--:Owner 读写,Group 和 Others 只读。用于普通配置文件
常用权限速查:600(SSH 私钥)、700(.ssh 目录)、777(所有权限,生产环境慎用)
Q2: 如何查看某个文件被哪个进程使用?
答案:
# lsof 查看文件被谁打开
lsof /var/log/syslog
# fuser 查看文件的进程
fuser -v /var/log/syslog
# 反向查询:某个进程打开了哪些文件
lsof -p <PID>
ls -la /proc/<PID>/fd/
Q3: /tmp 目录为什么设置 Sticky Bit?
答案:
/tmp 的权限是 1777(drwxrwxrwt),其中 Sticky Bit(t)确保:虽然所有用户都可以在 /tmp 创建文件,但只有文件的所有者或 root 才能删除该文件。这防止了用户 A 删除用户 B 的临时文件。
Q4: 一个用户同时属于多个组,权限如何判断?
答案:
Linux 权限判断顺序:
- 先检查是否是 Owner → 使用 Owner 权限
- 再检查是否属于 Group(包括所有附加组) → 使用 Group 权限
- 最后使用 Others 权限
如果有 ACL,还会额外检查 ACL 规则。注意:一旦匹配到某个层级,就不会再往下检查。
Q5: 如何安全地给普通用户授予部分 root 权限?
答案:
使用 sudo 精确授权:
# 在 /etc/sudoers.d/deploy 中
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart app
deploy ALL=(ALL) NOPASSWD: /usr/bin/tail -f /var/log/nginx/*
原则:
- 最小权限:只授予必要命令
- 限定参数:尽量指定完整命令而非通配
- 避免 shell 逃逸:不要授权
vim、less等可以执行 shell 的命令 - 日志审计:sudo 操作自动记录到
/var/log/auth.log