跳到主要内容

用户与权限管理

问题

请详细介绍 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 (读+写+执行)
└──────────── 文件类型: - (普通文件)

权限数字表示

权限字符数字
r4
w2
执行x1
-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,还有三种特殊权限位:

权限数字对文件对目录
SUID4以文件所有者身份执行无意义
SGID2以文件所属组身份执行新创建的文件继承目录的组
Sticky1无意义只有文件所有者才能删除文件
# 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 安全要点
  1. 始终使用 visudo 编辑:会做语法检查,防止配置错误导致 sudo 不可用
  2. 最小权限原则:只授予必要的命令权限
  3. 避免 ALL=(ALL) NOPASSWD: ALL:这等于给了 root 权限
  4. 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 的权限是 1777drwxrwxrwt),其中 Sticky Bit(t)确保:虽然所有用户都可以在 /tmp 创建文件,但只有文件的所有者或 root 才能删除该文件。这防止了用户 A 删除用户 B 的临时文件。

Q4: 一个用户同时属于多个组,权限如何判断?

答案

Linux 权限判断顺序:

  1. 先检查是否是 Owner → 使用 Owner 权限
  2. 再检查是否属于 Group(包括所有附加组) → 使用 Group 权限
  3. 最后使用 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/*

原则:

  1. 最小权限:只授予必要命令
  2. 限定参数:尽量指定完整命令而非通配
  3. 避免 shell 逃逸:不要授权 vimless 等可以执行 shell 的命令
  4. 日志审计:sudo 操作自动记录到 /var/log/auth.log

相关链接