Linux 用户与权限管理

本文合并自:02-用户和组管理.md、1-2-Linux用户与权限管理.md

本文以 CentOS 7 / RHEL 7 为主线,同时标注 CentOS 6 与 Ubuntu / Debian 的差异,系统讲解 Linux 用户与组的分类、四个核心配置文件(/etc/passwd、/etc/shadow、/etc/group、/etc/gshadow)字段含义、用户与组管理命令、su/sudo 身份切换与授权、文件权限体系(chmod/chown/chgrp)、特殊权限(SUID/SGID/Sticky)、ACL 扩展权限、umask 权限掩码、文件隐藏属性(chattr/lsattr),并附环境变量、命令别名、命令历史以及完整的课堂练习(PPP1–PPP17)与参考答案。

本章要点

  • 理解 Linux 三类用户(管理员、系统用户/伪用户、普通用户)及 UID/GID 取值范围,掌握 CentOS 与 Ubuntu 的差异。
  • 掌握 /etc/passwd、/etc/shadow、/etc/group、/etc/gshadow 四个核心配置文件的字段含义。
  • 熟练使用 useradd、usermod、userdel、passwd、chage、id、w、who 等命令管理用户。
  • 熟练使用 groupadd、groupmod、groupdel、gpasswd、groups、newgrp 等命令管理组。
  • 掌握 su 与 sudo 的区别及 /etc/sudoers 授权配置(含以非 root 用户为目标用户的授权)。
  • 理解 rwx 权限、八进制表示、权限判断顺序,能使用 chmod/chown/chgrp 修改权限与所有权。
  • 掌握 SUID、SGID、Sticky 三类特殊权限及 umask 权限掩码的正确计算方式。
  • 掌握 ACL 权限(getfacl/setfacl)与文件隐藏属性(chattr/lsattr)。
  • 了解用户环境变量配置文件、命令历史与命令别名。

一、用户与组的概念分类

1.1 用户分类

Linux 系统中的用户按 UID 范围分为三类:

用户类型 UID 范围 说明
管理员(root) 0 UID 必须为 0 且应保持唯一,默认为 root,拥有系统最高权限
系统用户(伪用户) CentOS:201–999
Ubuntu:100–999
默认不允许登录系统,用于给服务提供运行时的身份
普通用户 CentOS:1000–60000
Ubuntu:1000–29999
通过手工或命令创建,默认可以登录系统

注意:Red Hat(RHEL 7)官方文档已建议未来普通用户的起始 UID 使用 5000,以避开可能扩大的系统保留范围。

1.2 UID/GID 取值范围配置文件

CentOS / RHEL:/etc/login.defs

UID_MIN         1000
UID_MAX         60000
SYS_UID_MIN     201
SYS_UID_MAX     999

GID_MIN         1000
GID_MAX         60000
SYS_GID_MIN     201
SYS_GID_MAX     999
  • 0–200:系统自带,建议不要修改。
  • 201–999:可作为特殊服务运行时所用身份。
  • 1000–60000:普通用户 UID 取值范围。

Ubuntu:/etc/adduser.conf

FIRST_SYSTEM_UID=100
LAST_SYSTEM_UID=999
FIRST_SYSTEM_GID=100
LAST_SYSTEM_GID=999
FIRST_UID=1000
LAST_UID=29999
FIRST_GID=1000
LAST_GID=29999

1.3 组的分类:主组与附加组

  • 主组(初始组、基本组、默认有效组):即 /etc/passwd 第 4 列记录的 GID。每个用户必须且只能有一个主组,创建文件时文件的属组默认取主组。
  • 附加组(附加组、辅助组):记录在 /etc/group 第 4 列的成员列表中。一个用户可以同时属于多个附加组,附加组用于访问文件时的组权限匹配。

id 命令输出中的 gid= 是用户的主组(默认有效组),作用于创建文件时的属组;groups= 列出用户所属的全部组,作用于存取文件时的组权限匹配。可通过 newgrp 临时切换有效组。

1.4 用户与组相关配置文件总览

文件 作用
/etc/passwd 保存用户基本信息,所有用户可读
/etc/shadow 保存用户密码及过期策略,仅 root 可读
/etc/group 保存组基本信息
/etc/gshadow 保存组密码及组管理员信息
/etc/default/useradd useradd/adduser 命令创建用户时的默认值
/etc/login.defs 用户/组创建时的全局默认规则(UID/GID 范围、密码策略等)
/etc/skel 新建用户家目录模板,创建用户时该目录下的文件会被复制到新用户家目录

二、四个核心配置文件字段详解

2.1 /etc/passwd

/etc/passwd 保存用户的基本信息,所有用户可读。以 root 行为例:

root:x:0:0:root:/root:/bin/bash

各字段以 : 分隔,含义如下:

列 示例 含义
1 root 用户名
2 x 密码占位符,x 表示密码存放在 /etc/shadow;去掉 x(该字段为空)表示该用户无密码
3 0 UID,操作系统只识别 UID,不识别用户名
4 0 GID,用户所属主组(初始组)的 ID
5 root 描述信息(GECOS/注释),可按需修改,也可为空
6 /root 家目录
7 /bin/bash 默认登录 Shell(设为 /sbin/nologin 可禁止登录)

迁移(移动)用户家目录的一般步骤

当用户家目录所在设备空间不足时,可按下述步骤迁移:

  1. 预备一个有足够空间的存储设备,并完成挂载。
  2. 确保该用户已经登出。
  3. 暂时禁用该用户:sudo passwd -l <username>。
  4. 把用户的家目录移动(或复制)到新位置。
  5. 在 /etc/passwd 中修改对应用户的第 6 列(家目录路径)。
  6. 重新启用该用户:sudo passwd -u <username>。

参考操作:

# 1. 创建用户并设置密码
sudo useradd u1
sudo passwd u1

# 2. 禁用(锁定)用户
sudo passwd -l u1

# 3. 创建新家目录并修改属主
sudo mkdir /u1
sudo chown u1:u1 /u1

# 4. 复制原家目录内容(含隐藏文件),以下两种写法均可
sudo cp -a /home/u1/. /u1/           # 复制目录下全部内容(含隐藏文件)
sudo cp -a /home/u1/.[^.]* /u1/      # 仅复制隐藏文件(.bash* 等环境变量文件)

# 5. 修改 /etc/passwd 中 u1 的家目录为 /u1

# 6. 解锁用户
sudo passwd -u u1

# 7. 登录 u1 验证
su - u1

2.2 /etc/shadow

/etc/shadow 保存用户的密码信息与密码有效期策略,只有 root 可读:

root:!:17787:0:99999:7:::
列 含义
1 用户名
2 加密后的真实密码;以 * 或 ! 开头表示不能通过密码登录(登录页面无法登录);该字段为空表示空密码,登录无需密码
3 上次修改密码的时间(从 1970-01-01 到修改日的天数)
4 修改密码后多少天内不允许再次修改,0 表示不限制;该限制只对用户改自己密码生效,sudo 和 root 不受限
5 密码有效期,多少天内必须修改密码,99999 表示不限制
6 密码过期前提前多少天发出警告
7 密码过期后的宽限期(天数);为空表示随时可修改密码后正常登录;过期且宽限期也过后,用户无法自行登录,只能联系管理员
8 账号过期天数(自 1970-01-01 起算),多用于收费/授权系统
9 保留字段

更多说明请查看:man 5 shadow

警告:空密码字段意味着任何人都能以该用户身份直接登录,属于严重的安全风险,生产环境严禁使用。需要禁止密码登录时应使用 passwd -l 锁定,而不是清空密码字段。

忘记 root 密码的处理思路

  1. 在登录页面进入 GRUB 修改启动参数、进入单用户模式重置密码(需物理/控制台访问权限)。

  2. 如果还记得一个具有 sudo 权限的账号密码,可使用:

    sudo su - root

    此时需要输入的是当前账号的密码,而非 root 密码。

密码过期后还能登录吗

密码过期后不能再通过密码登录系统,但仍然可以通过其他方式登录/切换,例如 su。

2.3 /etc/group

组名:密码:GID:组成员
列 含义
1 组名
2 密码占位符,x 表示密码存放在 /etc/gshadow
3 GID
4 属于该组的用户名列表(附加组成员),以逗号分隔

2.4 /etc/gshadow

组名:密码:组管理员:组成员
列 含义
1 组名
2 组密码
3 组管理员
4 组成员

三、用户管理命令

3.1 创建用户:useradd / adduser

useradd a               # 创建用户 a
useradd -g soul a       # 新建用户 a,并指定其主组(初始组)为 soul
adduser a               # 创建用户(CentOS 下与 useradd 无区别)
命令 说明
useradd <username> 命令行创建用户
useradd -g <group> <username> 创建用户并指定初始组(主组)
adduser <username> 不同发行版行为不同,见下

CentOS 与 Ubuntu 的差异:

  • CentOS:useradd 和 adduser 没有区别(adduser 是 useradd 的符号链接),都会创建用户、家目录和邮箱,但新建用户默认没有密码,需要用 sudo passwd <username> 设置;也可以删除 /etc/shadow 中对应用户的第 2 列,使 su 登录时无需密码(不推荐,见安全警告)。
  • Ubuntu:adduser 是交互式创建用户脚本,会提示输入密码、注释等信息。

3.2 修改用户密码:passwd

passwd a            # 修改用户 a 的密码
passwd              # 修改当前用户自己的密码
passwd -l a         # 锁定用户 a(临时关闭),等价于在 /etc/shadow 第 2 字段前加 * 或 !
passwd -u a         # 解锁用户 a,等价于去掉 /etc/shadow 第 2 字段的 * 或 !

3.3 修改用户信息:usermod

选项 作用 示例
-u 修改 UID(目标 UID 可以不存在) sudo usermod -u 1004 u3
-g 修改主组/初始组 GID(该组必须已存在) sudo usermod -g 1001 u3
-d 修改家目录(配置与文件会自动处理) sudo usermod -d /u1 u3
-s 修改登录 Shell sudo usermod -s /sbin/nologin u3
-G 设置附加组(会覆盖原有附加组) sudo usermod -G soul a
-a -G(-aG) 追加附加组(不覆盖原有组) sudo usermod -aG g1,g2,g3 u3
-L 锁定用户密码(用户无法通过密码登录,但仍可通过 SSH 证书等方式登录) sudo usermod -L u1
-U 解锁用户密码 sudo usermod -U u1
-e 设定账号过期日期 sudo usermod -e "2014-01-01" u1
-e "" 清除账号过期日期 sudo usermod -e "" u1
-l 修改用户名 sudo usermod -l <newname> <currentname>
sudo usermod -u 1004 u3          # 修改 UID
sudo usermod -g 1001 u3          # 修改 GID,该组必须存在
sudo usermod -d /u1 u3           # 修改家目录
sudo usermod -aG g1,g2,g3 u3     # 追加附加组

3.4 删除用户:userdel

userdel a          # 删除用户 a(保留家目录和邮件目录)
userdel -r a       # 删除用户 a,并同时删除家目录和邮件目录(强烈建议使用)

3.5 密码策略:chage

chage 命令用于查看和修改用户密码 aging 策略,对应 /etc/shadow 中的各个字段。

chage -l <username>              # 查看用户密码策略信息
chage -M <天数> <username>       # 设置密码最长有效天数(对应 shadow 第 5 列)
chage -m <天数> <username>       # 设置密码最短修改间隔(对应 shadow 第 4 列)
chage -W <天数> <username>       # 设置密码过期前警告天数(对应 shadow 第 6 列)
chage -I <天数> <username>       # 设置密码过期后宽限天数(对应 shadow 第 7 列)
chage -E <日期> <username>       # 设置账号过期日期(YYYY-MM-DD,对应 shadow 第 8 列)
chage -d <天数> <username>       # 设置上次修改密码的日期(自 1970-01-01 起的天数)

chage -d 0 <username> 可强制用户下次登录时必须修改密码。

3.6 查看用户信息:id

id              # 查看当前登录用户的 UID、GID 及所属组列表
id <username>   # 查看指定用户的信息

3.7 查看在线登录用户:w / who

who             # 列出当前登录系统的用户、终端、登录时间和来源地址
who -b          # 显示系统最近一次启动时间
w               # 列出当前登录用户及其正在执行的命令,并显示系统负载
whoami          # 显示当前有效用户名
  • who 输出列依次为:用户名、登录终端(tty/pts)、登录时间、来源主机。
  • w 输出比 who 更详细,附加 IDLE(空闲时间)、JCPU/PCPU(CPU 占用时间)、WHAT(当前执行的命令)等列,首行还会显示系统时间、运行时长和平均负载。

3.8 批量创建与删除用户

配合 shell 循环可以批量完成用户的创建、设置密码与删除:

for i in {1..10}; do useradd u$i; done                            # 批量创建 u1~u10
for i in {1..10}; do echo "123456" | passwd --stdin u$i; done      # 批量设置密码
for i in {1..10}; do userdel -r u$i; done                          # 批量删除并清理家目录

注意:passwd --stdin 是 RHEL / CentOS 版 passwd 的专有选项,Ubuntu / Debian 的 passwd 不支持,需改用 chpasswd:

for i in {1..10}; do echo "u$i:123456" | chpasswd; done

3.9 手工创建用户(不使用 useradd)

直接通过修改配置文件创建用户 bean(UID/GID 均为 1003):

第一步:在 /etc/passwd 添加一行

bean:x:1003:1003::/home/bean:/bin/bash

第二步:修改 /etc/shadow

复制一个现有普通用户的行,再做对应修改(用户名、密码字段等)。

第三步:在 /etc/group 添加组信息

bean:x:1003:

第四步:在 /etc/gshadow 添加组密码信息

bean:!::

第五步:创建家目录并复制环境变量模板文件

mkdir /home/bean
cp /etc/skel/.bash* /home/bean
chown bean:bean /home/bean -R      # 等价于 chown -R bean:bean /home/bean
chmod 700 /home/bean -R            # 等价于 chmod -R 700 /home/bean

第六步:创建用户邮件文件

touch /var/mail/bean
chown bean:bean /var/mail/bean
chmod 660 /var/mail/bean

四、组管理命令

4.1 groupadd / groupdel / groupmod

sudo groupadd g3               # 创建组 g3
sudo groupdel g3               # 删除组 g3
sudo groupmod -g 1003 a1       # 将组 a1 的 GID 修改为 1003

注意:不能删除一个用户的主组(基本组)。必须先删除该用户,才能删除其主组。

4.2 gpasswd

gpasswd a1                  # 修改组 a1 的密码
sudo gpasswd -a a root      # 将用户 a 加入 root 组
sudo gpasswd -A a root      # 将用户 a 设为 root 组的管理员
sudo gpasswd -A a,b root    # 将 a、b 设为 root 组的管理员
sudo gpasswd -A "" root     # 清空 root 组的管理员
sudo gpasswd -d a root      # 将用户 a 从 root 组中删除
sudo gpasswd -M u1,u2 g1    # 设置 g1 的组成员为 u1、u2(会覆盖原有成员列表)
命令 示例 说明
groupadd sudo groupadd g3 创建新组
groupdel sudo groupdel g3 删除组,不能删除用户的基本组,需先删除用户
groupmod -g sudo groupmod -g 1003 a1 修改组 GID
gpasswd gpasswd a1 修改组密码
gpasswd -a gpasswd -a a root 将用户 a 加入 root 组
gpasswd -A gpasswd -A a root 设置用户 a 为 root 组管理员
gpasswd -A gpasswd -A a,b root 设置 a、b 为 root 组管理员
gpasswd -A "" gpasswd -A "" root 清空 root 组管理员
gpasswd -d gpasswd -d a root 将 a 从 root 组移除
gpasswd -M gpasswd -M u1,u2 g1 设置 g1 组成员为 u1、u2(覆盖)
newgrp newgrp root 临时切换当前用户的有效组,重新登录后失效

组管理提示:

  • 一个用户可同时属于多个组,但只有 root 有权设置组管理员。
  • 使用 gpasswd -A 添加组管理员会覆盖已有管理员列表;如需追加多个管理员,可手动修改 /etc/gshadow 第 3 列。
  • 组管理员可以添加和删除组员。
  • 组管理员删除另一个组管理员时,只是删除其普通成员身份,对方仍具有管理员权限。
  • 组管理员可以将自己从组中删除。

4.3 groups

groups              # 查看当前用户所属的全部组(第一个为主组)
groups <username>   # 查看指定用户所属的全部组

4.4 newgrp

newgrp root     # 将当前用户临时切换有效组为 root 组,重新登录后失效
  • 若用户不属于目标组,且该组没有设置组密码,则无法通过 newgrp 切换。
  • 若用户已属于目标组,切换时不需要输入密码。
  • 切换有效组后,新建文件的属组即为切换后的组。

五、身份切换:su 与 sudo

5.1 su

su - a     # 完全切换:不继承上一个用户的环境变量,加载目标用户的 profile(sbin 下命令可正常调用路径)
su a       # 不完全切换:继承上一个用户的环境变量
su - root  # 切换到 root(需输入 root 密码)
命令 说明
su - <user> 完全切换,不继承上一个用户环境变量
su <user> 不完全切换,继承上一个用户环境变量

说明:su a(不完全切换)继承原用户的 PATH 等环境变量;su - a(完全切换)重新加载目标用户的环境变量配置文件。两者对 /sbin、/usr/sbin 下命令的可用性有影响,实际以目标用户 PATH 为准。

5.2 sudo 授权

普通用户默认没有 sudo 授权,因此无法使用 sudo。sudo 只能执行外部命令,并且只能执行 secure_path 变量所保存目录中的命令。

授权流程

  1. 切换到 root(或具有修改 /etc/sudoers 权限的用户):

    su root
    # 或
    sudo -i
  2. 编辑 sudo 配置(推荐使用 visudo,它会进行语法检查):

    visudo
    # 或
    vim /etc/sudoers
  3. 添加授权规则。

sudo 规则格式

用户名 机器名=(目标用户名:目标组) 命令列表

其中 (目标用户名:目标组) 中的组部分可省略,写作 (目标用户名)。

授权示例

# 给 tom 用户授予完整 sudo 权限
tom ALL=(ALL:ALL) ALL

# 给 tom 用户组授予完整 sudo 权限(% 表示组)
%tom ALL=(ALL:ALL) ALL

# 授权单个命令:soul 用户可以 root 身份执行 ls 和 cat
soul ALL=(root) /bin/ls,/bin/cat

# 部分命令不需要密码,部分需要密码,可以分成多行书写
u2 ALL=(root) NOPASSWD: /bin/cat
u2 ALL=(root) /bin/mkdir

(目标用户名) 不限于 root,也可以指定普通用户,表示只允许以该用户身份执行命令:

# 允许 soul 以 u1 身份执行 ls(需输入 soul 自己的密码)
soul ALL=(u1) /bin/ls

# 允许 soul 以 u1 身份免密执行 cat
soul ALL=(u1) NOPASSWD: /bin/cat

# 允许 u1 以任意用户身份免密执行 fdisk
u1 ALL=(ALL) NOPASSWD: /bin/fdisk

执行时用 -u 指定目标用户,否则默认以 root 身份运行(会因未授权而被拒绝):

sudo -u u1 ls /home/u1

查看命令的绝对路径可使用 whereis <command>,例如 whereis mkdir。


六、文件权限

6.1 ls -l 解读

使用 ls -l 查看文件权限:

ls -l /tmp/readme.txt
ls -hl /tmp/readme.txt      # -h 以人类可读单位显示大小
-rw-r--r-- 1 root root 4383 2011-03-01 01:37 readme.txt

权限字符串共 10 位:

位 含义
第 1 位 文件类型:- 普通文件,d 目录,l 符号链接,b 块设备,c 字符设备,p 管道,s socket
第 2–4 位 所属用户(属主)权限,u
第 5–7 位 所属组权限,g
第 8–10 位 其他用户权限,o
-  rw-       r--       r--
   所属用户u  所属组g    其他人o
  • u(user):文件所有者的权限。
  • g(group):文件所属组的权限。
  • o(other):其他用户的权限。
  • a(all):以上三者的总称。

ls -l 其余各列依次为:硬链接数、所属用户、所属组、文件大小(字节)、最后修改时间、文件名。

权限字符的含义

权限 对文件 对目录
r(read,4) 读取文件内容 列出目录中的文件列表
w(write,2) 修改文件内容 在目录中创建、删除、重命名文件/子目录
x(execute,1) 执行文件(文件必须是可执行程序或脚本) 切换(进入 cd)该目录

6.2 二进制与八进制权限

权限位可用三位二进制表示,再转为八进制:

二进制 八进制 权限
000 0 ---
001 1 --x
010 2 -w-
011 3 -wx
100 4 r--
101 5 r-x
110 6 rw-
111 7 rwx

例如 rwxr-xr-x:

rwx  r-x  r-x
421  401  401
 7    5    5

即八进制 755。

6.3 修改权限:chmod

chmod u+x,g+r,o-r file          # 符号方式增减权限
chmod u=rwx,g=rw,o=r file       # 符号方式设定(赋值)权限,结果为 rwx rw- r--
chmod 755 file                  # 数字(八进制)方式设定权限,结果为 rwx r-x r-x
chmod 755 dirs -R               # 递归修改目录下所有文件权限为 755
chmod -R 755 dirs               # 同上,选项位置可前置
chmod a+x file                  # 给所有身份加执行权限
chmod o= file                   # 清空其他用户的所有权限

6.4 权限判断顺序

  1. 先判断是否为文件的所有者;若是,执行所有者(u)权限后结束。
  2. 若不是所有者,判断是否属于文件所属组(主组或附加组均可);若是,执行所属组(g)权限后结束。
  3. 若都不是,执行其他人(o)权限。

因为判断到即结束,所以会出现「所有者权限比其他人还小」的情况,例如 chmod 466 file 时,属主反而只能读不能写。

安全提示:公开目录不要随意添加权限,最大权限不要超过 755;给其他用户加 w 权限要谨慎。即使只给了其他用户 3(-wx)权限,别人也可能进入目录修改文件并强制保存(:wq!),从而将文件据为己有(变更所有者)。

6.5 修改所有权:chown / chgrp

修改文件的所有者或所属组需要 root 权限。

sudo chown tom file               # 修改文件所属用户为 tom
sudo chown :tom file              # 修改文件所属组为 tom
sudo chgrp tom file               # 同上,使用 chgrp 修改所属组
sudo chown tom:jack file          # 同时修改所属用户为 tom、所属组为 jack
sudo chown jack.root dirs -R      # 递归修改目录下所有文件的所属用户为 jack、所属组为 root
sudo chown -R jack:root dirs      # 同上,选项前置写法
sudo chgrp -R tom dirs            # 递归修改所属组

chown user.group 与 chown user:group 两种写法均可。


七、特殊权限:SUID / SGID / Sticky

命令 说明
chmod u+s file 设置 SUID(SetUID)
chmod g+s file 设置 SGID(SetGID,对目录同样有效)
chmod u-s file 取消 SUID
chmod g-s file 取消 SGID
chmod o+t dir 设置 Sticky(粘贴位)
chmod o-t dir 取消 Sticky

7.1 对可执行文件设置 SUID / SGID

  • 未设置特权位时,命令运行时采用运行者的身份。
  • 设置特权位后,命令运行时采用的身份不再是运行者,而是命令文件本身的所属者(SUID)或所属组(SGID)。
  • 典型例子:/usr/bin/passwd(普通用户改自己密码需要写 /etc/shadow)、touch。
ls -l /usr/bin/passwd
# -rwsr-xr-x. 1 root root ... /usr/bin/passwd

7.2 对目录设置 SGID

对目录设置组特权位(SGID)后,在该目录下创建的子文件或子目录会自动继承该目录的所属组身份;子目录还会继承 SGID 特权位。

对目录只能设置组特权(SGID),设置 SUID 无实际意义(Linux 忽略目录上的 SUID)。任何用户在设置了 SGID 的目录下创建文件,其所属组都为目录的所属组(root 也不例外)。

实验示例:让 mary 通过 SUID 程序以 tom 身份创建文件

mkdir -p /tmp/test/{tom,mary}
sudo chown tom:tom /tmp/test/tom -R
sudo chown mary:mary /tmp/test/mary -R
sudo chmod 700 /tmp/test/{mary,tom} -R

sudo cp /usr/bin/touch /tmp/test/mary/tomCreate
sudo chown tom:tom /tmp/test/mary/tomCreate
sudo chmod u+x /tmp/test/mary/tomCreate
sudo chmod u+s /tmp/test/mary/tomCreate

# 切换到 mary 执行 SUID 程序
su - mary
/tmp/test/mary/tomCreate /tmp/test/tom/mary.file
# 查看新创建文件的所有者,应为 tom
ls -l /tmp/test/tom/

7.3 粘贴位:Sticky

粘贴位只对目录有效,用于防止其他用户删除文件。设置后,即使目录对其他人可写,也只有文件所有者、目录所有者和 root 才能删除或重命名该目录下的文件。典型应用:/tmp。

chmod o+t dirs      # 给目录设置粘贴位
chmod o-t dirs      # 取消粘贴位

实验示例:

cd /
ls -l /                    # 查看 /tmp 目录的权限(默认为 drwxrwxrwt,带 sticky 位)
touch /tmp/uplooking.txt
chmod 777 /tmp/uplooking.txt
su - u1
rm /tmp/uplooking.txt      # 尝试删除(应失败,因为 /tmp 有 sticky 位)
exit
sudo chmod o-t /tmp
rm /tmp/uplooking.txt      # 再次尝试删除(应成功)
sudo chmod o+t /tmp        # 恢复 sticky 位

7.4 特殊权限的大小写显示

SUID/SGID 显示在所有者/所属组的 x 位上,Sticky 显示在其他人的 x 位上。

  • 若该位原本有 x 权限,特殊权限显示为小写(s、s、t)。
  • 若该位原本没有 x 权限,特殊权限显示为大写(S、S、T)。

八、ACL 扩展权限:getfacl / setfacl

基本权限只能表示所有者、所属组、其他人三类身份。当需要对单个用户或单个组单独设置 rwx 权限时,需要使用 ACL(Access Control List)。

文件系统支持情况(版本差异):

  • CentOS 6:新建分区可能需要手动开启 ACL 功能(mount -o acl 或在 /etc/fstab 中添加 acl 挂载选项;ext2/ext3 需显式启用)。
  • CentOS 7:默认使用 XFS 文件系统,ACL 自动启用,无需手动开启。
  • 不能将带有 ACL 权限的文件拷贝到未启用 ACL 的分区(ACL 会丢失)。

8.1 设置 ACL 权限:setfacl

sudo setfacl -m u:username:rwx /path/filename       # 给指定用户设置 ACL
sudo setfacl -m u:u1:rwx /tmp/1_acl.txt             # 示例:给用户 u1 授予 rwx
sudo setfacl -m u:u1:rwx /testdir                   # 对目录设置
sudo setfacl -mR u:u1:rwx /testdir                  # 递归对目录设置(也可写作 -Rm)
sudo setfacl -Rm u:u1:rwx /testdir                  # 同上
sudo setfacl -m g:groupname:rwx /path/filename      # 给指定组设置 ACL

设置后用 ls -l 查看,权限位末尾会出现 + 号,表示该文件具有 ACL 权限。

8.2 查看 ACL 权限:getfacl

getfacl /tmp/1_acl.txt          # 查看文件的 ACL 权限
getfacl /acl/1_acl.txt

8.3 ACL 判断顺序

完整的权限判断顺序(含 ACL)为:

所有者 -> 命名用户/命名组(ACL 条目) -> 所属组 -> 其他用户

即在传统的「所有者 → 所属组 → 其他用户」顺序中,ACL 的命名用户/命名组条目插在所有者之后、所属组之前进行匹配。

8.4 删除 ACL 权限

setfacl -k dir      # 删除目录的默认(default)ACL 权限
setfacl -b file     # 去除文件上的所有 ACL 属性

8.5 复制时保留 ACL

cp /tmp/1_acl.txt ~/         # 不会保留 ACL 权限
cp -p /tmp/1_acl.txt ~/      # 会保留 ACL 权限(同时保留属主、时间戳等)

九、权限掩码:umask

umask 用于设置创建文件或目录时的默认权限掩码。

用户类型 默认 umask
root(管理员) 022
普通用户 002

9.1 正确的计算方式

umask 是一个掩码,作用是把默认权限中对应的权限位「去掉」:

实际权限 = 默认权限 AND (NOT umask)
  • 目录的默认权限基数是 777。
  • 文件的默认权限基数是 666,而不是 777,因为新建的普通文件通常不需要执行位,系统不会主动赋予 x。
身份 对象 默认权限 umask 实际权限
root 目录 777 022 755
root 文件 666 022 644
普通用户 目录 777 002 775
普通用户 文件 666 002 664
umask                # 查看当前权限掩码
umask 0077           # 修改当前权限掩码为 0077(仅对当前 shell 进程临时生效)
umask 0222           # 去除写权限
umask 0000           # 不屏蔽任何权限

修改 umask 只影响当前 shell 进程及其子进程,重启终端后失效。要永久生效需写入 ~/.bashrc、~/.bash_profile 或 /etc/profile。

9.2 关于「异或算法」的常见误区

部分讲义把 umask 的计算描述为「默认权限与 umask 做异或(相同为 0,不同为 1)」,其按位演算示例如下:

0777  111 111 111
0002  000 000 010
      111 111 101   = 775

注意:这种理解是不正确的。异或只是在 002、022 这类常见掩码下碰巧得到了相同结果。例如 umask 003 时,文件实际权限应是 666 AND (NOT 003) = 664,而按异或计算会得出错误的 665。

同理,也不要用「777 - umask」做减法:umask 003 时 666 - 003 = 663,同样是错的。

只有用「掩码屏蔽权限位」(默认权限 AND (NOT umask))来理解才始终正确。


十、文件隐藏属性:chattr / lsattr

命令 说明
lsattr 查看当前目录下文件的特殊(隐藏)属性
lsattr file 查看指定文件的特殊属性
chattr +i file 添加 i(immutable)属性:不可修改、不可删除、不可重命名,管理员也不能直接更改
chattr +a file 添加 a(append only)属性:只能追加内容,不能修改或覆盖
chattr -i file 取消 i 属性
chattr -a file 取消 a 属性
lsattr
sudo chattr +i file
sudo chattr +a file
sudo chattr -i file
sudo chattr -a file
sudo chattr +i /tmp/uplooking.txt
sudo chattr -i /tmp/uplooking.txt
sudo chattr +a /tmp/uplooking.txt

如果文件同时有 i 属性,需要先取消 i 才能设置 a 属性。

安全边界说明:chattr +i 可以阻止包括 root 在内的所有用户直接修改或删除文件,但并非绝对不可逆:root(具备 CAP_LINUX_IMMUTABLE 能力)仍可执行 chattr -i 解除后再操作。因此它是「防误操作」手段,不能当作安全边界;解除前请确认业务影响。

实验示例:

touch /tmp/uplooking.txt
chmod 777 /tmp/uplooking.txt
sudo chattr +i /tmp/uplooking.txt
# 尝试用 vim 编辑保存、用 > 和 >> 重定向,观察是否成功(均应失败)
sudo chattr +a /tmp/uplooking.txt    # 因已有 i 属性,此操作会失败
sudo chattr -i /tmp/uplooking.txt
sudo chattr +a /tmp/uplooking.txt    # 现在可以成功
# 用 vim 编辑文件保存(vim 不会提示只读,但保存会失败)
echo "hello world" >> /tmp/uplooking.txt   # 追加写入应该成功
echo "hello world" > /tmp/uplooking.txt    # 覆盖写入应该失败

十一、环境变量、命令别名与命令历史

11.1 查看变量

命令 作用
env 显示当前 shell 的环境变量(包含用户环境变量)
set 显示当前 shell 的所有变量(含私有变量),按变量名排序
export 显示已导出为用户/环境变量的 shell 变量及其属性,按变量名排序

11.2 用户环境变量配置文件

位于用户家目录(/home/<用户名>/ 或 /root/)下:

文件 作用
~/.bash_history 记录用户执行过的历史命令;用户退出登录后才会将当前命令历史写入此文件
~/.bash_logout 用户退出登录时执行的脚本;需通过 logout 或 exit 退出才生效
~/.bash_profile 用户环境变量的常规设定位置,用户登录时执行
~/.bashrc 命令别名的设定位置,每次打开新终端时执行

11.3 全局环境变量配置文件

文件 作用
/etc/bashrc 全局 bash 配置(全局别名和函数),影响所有用户
/etc/profile 全局环境变量配置,影响所有用户

修改后使其立即生效:

source /etc/profile
# 或
. /etc/profile

11.4 命令历史:history

history                 # 查看当前用户的历史命令
history 10              # 显示最后(最近)10 条历史命令
history -w b.history    # 将当前命令历史写入文件
history -r a.history    # 从文件读取命令历史到历史列表
history -c              # 清除(清空)当前命令历史列表

历史命令调用快捷方式:

符号 作用
!! 重复执行上一条命令
!a 重复执行最近一条以 a 开头的命令
!100 重复执行历史记录中第 100 条命令
!$ 获取上一条命令的最后一个参数(常用于获取路径)

11.5 命令别名:alias

alias                       # 列出当前所有别名
alias ls='ls -l'            # 创建别名(仅当前 shell 生效,重启终端失效)
unalias ls                  # 取消别名

将别名写入 ~/.bashrc 可永久生效:

echo "alias ms='sudo mount 192.168.0.183:/soul /mnt'" >> ~/.bashrc
echo "alias ums='sudo umount /mnt'" >> ~/.bashrc
. ~/.bashrc                 # 重新加载配置使其生效

也可将 set -o vi 等设置加入 ~/.bashrc:

echo "set -o vi" >> ~/.bashrc

11.6 常用 Bash 快捷键

快捷键 作用
Tab 第一次补全命令或文件名,按两次列出所有匹配项
Ctrl + C 终止(结束)当前任务
Ctrl + A 光标跳到行首
Ctrl + E 光标跳到行尾
Ctrl + L 清屏
Ctrl + D 退出当前终端(等同于 exit)

十二、练习题与参考答案

PPP1:用户增删改查

题目:创建用户并设置密码,查询用户信息在配置文件中的变化,用该用户登录后再删除。

参考答案:

useradd u1001
passwd u1001
# 查看 /etc/passwd 和 /etc/shadow 中新增的行
grep u1001 /etc/passwd /etc/shadow /etc/group /etc/gshadow
# 用 u1001 在文本控制台(Ctrl+Alt+F2)登录验证
userdel -r u1001

要点:useradd 会同时在 /etc/passwd、/etc/shadow、/etc/group、/etc/gshadow 中新增记录,并创建家目录和邮件文件;userdel -r 会一并清除家目录和邮件文件。

PPP2:批量创建与删除用户

题目:创建 10 个用户 u1 到 u10,统一设置密码 123456,验证后全部删除(含家目录)。

参考答案:

for i in {1..10}; do useradd u$i; done                            # 批量创建
for i in {1..10}; do echo "123456" | passwd --stdin u$i; done      # 批量设置密码
for i in {1..10}; do userdel -r u$i; done                          # 批量删除并清理家目录

passwd --stdin 仅 RHEL / CentOS 可用;Ubuntu / Debian 请改用 chpasswd:

for i in {1..10}; do echo "u$i:123456" | chpasswd; done

PPP3:用户管理综合操作

题目:完成用户的创建、删除、设密码、登录、锁定/解锁、账号过期设置与清除、修改主组、查看信息、改名等一整套操作,并观察每一步的报错信息。

参考答案:

# 1. 创建用户
useradd u1
# 2. 删除用户
userdel -r u1
# 3. 再次创建用户
useradd u1
# 4. 设置密码
sudo passwd u1
# 5. 切换登录
su - u1
# 6. 锁定用户密码
sudo usermod -L u1
# 7. 再次登录查看报错(提示认证失败)
su - u1
# 8. 解锁用户密码
sudo usermod -U u1
# 9. 设置账号过期
sudo usermod -e "2014-01-01" u1
# 10. 登录查看报错(提示账号已过期)
su - u1
# 11. 清除过期信息
sudo usermod -e "" u1
# 12. 修改初始组(主组)
sudo usermod -g <gid> u1
# 13. 查看用户信息
id u1
# 14. 修改用户名
sudo usermod -l <newname> u1
# 15. 用新用户名登录,查看家目录路径

要点:usermod -l 只改用户名,不会自动改家目录名,登录后 pwd 仍是原家目录路径;如需同步需配合 usermod -d。

PPP4:sudo 授权

题目:创建用户 u1、u2,通过 visudo 配置多条授权规则(含指定非 root 目标用户、免密与需密码两类),并逐条验证。

参考答案:

  1. 创建用户:
sudo useradd u1
sudo useradd u2
  1. 通过 visudo 配置以下规则(将 soul 替换为当前用户名):
# 以 u1 身份执行 ls(需输入 soul 自己的密码)
soul ALL=(u1) /bin/ls
# 以 u1 身份执行 cat,不需要密码
soul ALL=(u1) NOPASSWD: /bin/cat
# 以 u2 身份执行任意命令
soul ALL=(u2) ALL
# 以 root 身份执行 ifconfig,不需要密码
soul ALL=(root) NOPASSWD: /sbin/ifconfig
# 以 root 身份执行 fdisk,需要密码
soul ALL=(root) /sbin/fdisk
# u1 以 root 身份执行 fdisk,不需要密码
u1   ALL=(root) NOPASSWD: /sbin/fdisk
# u1 以 root 身份执行 mkdir
u1   ALL=(root) /bin/mkdir
# u1 以任意用户身份免密执行 fdisk
u1   ALL=(ALL) NOPASSWD: /bin/fdisk
  1. 验证:
# 指定目标用户执行,否则默认以 root 身份运行而被拒绝
sudo -u u1 ls /home/u1
sudo -u u1 cat /home/u1/.bashrc

su - u1
sudo mkdir /test        # 未授权前会失败(提示 u1 is not in the sudoers file)
# 在 sudoers 中添加 u1 ALL=(root) /bin/mkdir,再测试
# 用同样方式测试 rm、cat、useradd 等命令

要点:命令必须写绝对路径(可用 whereis <command> 查询);sudo 只能执行 secure_path 中的外部命令;务必用 visudo 编辑以获得语法检查。

PPP5:组管理综合操作

题目:创建三个组并删除其中一个,创建两个用户,完成组成员的批量设置、移除,以及组管理员设置,并验证 newgrp 行为。

参考答案:

# 1. 创建三个组
sudo groupadd g1
sudo groupadd g2
sudo groupadd g3
# 2. 删除组 g3
sudo groupdel g3
# 3. 创建用户 u1、u2
sudo useradd u1
sudo useradd u2
# 4. 将 u1、u2 加入 g1(覆盖式设置成员列表)
sudo gpasswd -M u1,u2 g1
# 5. 将 u2 从 g1 删除
sudo gpasswd -d u2 g1
# 6. 将 u1、u2 设为 g1 的管理员
sudo gpasswd -A u1,u2 g1

验证要点:

  • 如果用户不属于某个组,且该组也没有设置密码,该用户无法通过 newgrp 切换到该组。
  • 如果用户已属于某个组,切换到该组时不需要密码。
  • 组管理员可以将其他用户加入或移出组,也可以将自己从组中删除。
  • 不能删除某个用户的主组,必须先删除该用户。

PPP6:移动用户家目录

题目:将用户 u1 的家目录从 /home/u1 迁移到 /u1,并保证用户能正常登录使用。

参考答案(步骤):

  1. 预备一个有足够空间的存储设备并挂载。
  2. 确保该用户已经登出。
  3. 暂时禁用用户:sudo passwd -l u1。
  4. 将家目录移动或复制到新位置。
  5. 修改 /etc/passwd 中对应用户的第 6 列。
  6. 解锁用户:sudo passwd -u u1。

参考命令:

sudo useradd u1
sudo passwd u1
sudo passwd -l u1
sudo mkdir /u1
sudo chown u1:u1 /u1
sudo cp -a /home/u1/. /u1/         # 或 sudo cp -a /home/u1/.[^.]* /u1/
# 修改 /etc/passwd 中 u1 的家目录为 /u1
sudo passwd -u u1
# 登录 u1 验证
su - u1

要点:必须使用 cp -a(或 -p)保留权限与属主;不要遗漏 .bash* 等隐藏文件;也可直接使用 usermod -d /u1 u1 由命令完成配置修改。

PPP7:无密码登录

题目:用两种方法实现用户无密码即可登录。

参考答案:

  1. 修改 /etc/passwd:将对应用户第 2 列的 x 删除(该字段留空)。
  2. 修改 /etc/shadow:将对应用户第 2 列的加密密码内容删除(保留冒号分隔符)。

安全警告:空密码意味着任何人都能以该用户身份登录,属于严重安全风险,仅可用于实验环境,生产环境严禁使用。禁止密码登录应使用 passwd -l 锁定。

PPP8:两种方法给用户改名

题目:用两种方法把用户改名。

参考答案:

  1. 使用命令:sudo usermod -l <newname> <oldname>。
  2. 直接修改配置文件:编辑 /etc/passwd(以及 /etc/shadow、/etc/group、/etc/gshadow 中对应的用户名字段)。

PPP9:文件权限管理(chmod 符号模式)

题目:对文件依次完成删除全部权限、逐类增删 rwx、组合修改、以及最终设置为 rwxr-xr-- 的操作。

参考答案:

# 1. 删除文件所有权限
sudo chmod 000 5_PPP9.txt
# 2. 给所有者添加读权限
sudo chmod u+r 5_PPP9.txt
# 3. 给所有者赋予 rwx
sudo chmod u=rwx 5_PPP9.txt
# 4. 给所属组添加读权限
sudo chmod g+r 5_PPP9.txt
# 5. 给所属组赋予 rwx
sudo chmod g=rwx 5_PPP9.txt
# 6. 给其他用户添加读权限
sudo chmod o+r 5_PPP9.txt
# 7. 给其他用户赋予 rwx
sudo chmod o=rwx 5_PPP9.txt
# 8. 删除其他用户的写权限
sudo chmod o-w 5_PPP9.txt
# 9. 删除其他用户的所有权限
sudo chmod o-r,o-w,o-x 5_PPP9.txt
# 10. 删除所属组写权限,同时删除其他用户所有权限
sudo chmod g-w,o= 5_PPP9.txt
# 11. 设置权限为 rwxr-xr--(两种等价写法)
sudo chmod 754 5_PPP9.txt
sudo chmod u=rwx,g=r-x,o=r-- 5_PPP9.txt

进一步实验:在自己的目录下创建文件,分别设置权限为 600、060、006,尝试用 vim 编辑并保存(含 :wq! 强制保存),观察普通用户与 sudo 下的差异。

要点:权限判断「命中即结束」,所以属主为 0 时即使组和其他人有权限,属主也无法读写;root 与 sudo 不受普通权限位限制。

PPP10:SUID / SGID / Sticky

题目:给二进制可执行文件加 SUID,给文件或目录加 SGID,给目录加 Sticky,并用 ls -l 观察权限位显示。

参考答案:

chmod u+s <filename>     # 给二进制可执行文件加 SUID
chmod g+s <filename>     # 给文件或目录加 SGID
chmod o+t <dirname>      # 给目录加 sticky
ls -l                    # 观察 s/S、t/T 的显示位置与大小写

要点:对应位原本有 x 则显示小写 s/t,无 x 则显示大写 S/T。

PPP11:数字方式设置权限

题目:使用八进制数字方式为文件和目录设置各种权限组合,并说明每种组合的实际效果。

参考答案:

sudo chmod 750 1_test.txt    # 所有者 rwx,属组 r-x,其他无权限
sudo chmod 575 1_test.txt    # 所有者 r-x,属组 rwx,其他 r-x
sudo chmod 770 1_test        # 目录:所有者和属组 rwx,其他无权限
sudo chmod 777 1_test        # 目录:所有人 rwx
sudo chmod 755 1_test.txt    # 所有人可读可执行,只有所有者可修改
sudo chmod 644 1_test        # 目录:所有人可列出内容(无 x 故不能进入),只有所有者可添加

要点:目录缺少 x 时即使有 r 也无法 cd 进入,且无法读取目录内文件的元数据。

PPP12:gid 与 groups 的区别

题目:验证 gid(主组/有效组)作用于创建文件时的属组,groups(全部所属组)作用于访问文件时的权限匹配。

参考答案(步骤):

  1. 创建组 g1、g2 和用户 u1。
  2. 将 u1 加入 g1 和 g2,并将 g1 设为默认有效组(主组)。
  3. 以 u1 登录并创建文件,ls -l 查看属组,应为 g1。
  4. 执行 newgrp g2 切换有效组,再创建文件,对比属组,应为 g2。
  5. 验证 groups 对访问的影响:
    • 让 u1 只属于 g1。
    • root 创建文件 f1,权限 740,属组为 g1,u1 应可读。
    • root 创建文件 f2,权限 740,属组为 g2,u1 应不可读。
    • 将 u1 加入 g2 后,u1 应能读 f2,同时仍能读 f1。

参考命令:

sudo groupadd g1
sudo groupadd g2
sudo useradd -g g1 u1
sudo gpasswd -a u1 g2
su - u1
touch a.txt && ls -l a.txt      # 属组为 g1
newgrp g2
touch b.txt && ls -l b.txt      # 属组为 g2

结论:gid(主组/有效组)决定新建文件的属组;groups(全部所属组,含附加组)决定访问已有文件时能否匹配到组权限。

PPP13:组管理员是否可以不属于该组

题目:验证一个不属于某组的用户能否被设置为该组的管理员。

参考答案(步骤):

  1. 创建组 g1 和用户 u1、u2、u3。
  2. 将 u1、u2 加入 g1。
  3. 尝试将不属于 g1 的 u3 设为 g1 的管理员,观察结果。
sudo groupadd g1
sudo useradd u1; sudo useradd u2; sudo useradd u3
sudo gpasswd -M u1,u2 g1
sudo gpasswd -A u3 g1
grep g1 /etc/gshadow

结论:gpasswd -A 可以把不属于该组的用户写入 /etc/gshadow 的管理员字段,即组管理员不必是该组成员;该用户随后即可对该组执行 gpasswd -a/-d 操作。同时注意 gpasswd -A 会覆盖原有管理员列表,如需保留多个管理员应直接编辑 /etc/gshadow。

PPP14:体验 SUID 和 SGID

题目:通过给 /bin/cat 临时加 SUID/SGID,体会特权位对身份的影响,并在测试后恢复原始权限。

参考答案(步骤):

  1. 用普通用户读取一个只有 root 可读的文件(如 /etc/shadow),观察结果(Permission denied)。
  2. 用 root 给 /bin/cat 加上 SUID 位,再次用普通用户读取,观察结果(可以读取成功)。
sudo chmod u+s /bin/cat
su - u1
cat /etc/shadow
exit
  1. 恢复 /bin/cat 的权限:
sudo chmod u-s /bin/cat
  1. 类似地,给 /bin/cat 加 SGID 位并配合文件属组权限进行测试:
sudo chmod g+s /bin/cat
# 准备一个属组为特定组、组权限可读而其他人不可读的文件,用普通用户读取验证
sudo chmod g-s /bin/cat
  1. 测试完毕后务必恢复原始权限。

安全警告:给 cat、vim、find 等通用命令加 SUID 等同于把 root 权限暴露给所有用户,仅可在实验环境短暂验证,验证后立即恢复。

PPP15:umask 实验

题目:查看当前 umask,分别在默认掩码、0222、0000 三种情况下新建文件和目录,验证实际权限是否符合「默认权限 AND (NOT umask)」。

参考答案:

# 1. 查看当前 umask,创建文件和目录查看默认权限
umask
touch file1
mkdir dir1
ls -l file1 dir1
# 普通用户默认 umask 002:文件 664,目录 775
# root 默认 umask 022:文件 644,目录 755

# 2. 修改 umask 为 0222 以去除写权限
umask 0222
touch file2
mkdir dir2
ls -l file2 dir2
# 文件 444,目录 555

# 3. 修改 umask 为 0000(不屏蔽任何权限)
umask 0000
touch file3
mkdir dir3
ls -l file3 dir3
# 目录 777,文件 666
# 文件不会有执行权限,因为 touch 创建文件时默认不包含执行位(基数为 666)

要点:不要用异或或减法计算 umask,见「九、权限掩码:umask」中的误区说明。

PPP16:用 strace 验证 touch 和 mkdir 的创建权限

题目:用 strace 追踪 touch 和 mkdir 的系统调用,验证它们请求的创建权限基数分别是 0666 和 0777。

参考答案:

# 追踪 touch 的系统调用,输出重定向到文件(strace 输出在标准错误)
strace touch file1 2> /tmp/strace.log
# 在日志中查找 open/openat/creat 调用的 mode 参数,应为 0666
vim /tmp/strace.log

# 追踪 mkdir
strace mkdir dir1 2> /tmp/strace.log
# 在日志中查找 mkdir 调用的 mode 参数,应为 0777
vim /tmp/strace.log

追踪正在运行的进程(假设 PID 为 2651):

strace -p 2651 2> /tmp/trace

结论:内核最终权限 = 程序请求的 mode AND (NOT umask),这解释了为什么文件基数是 666、目录基数是 777。

PPP17:ACL 权限

题目:创建权限为 775 的 /acl 目录,在其中创建权限为 770 的文件,给不属于该文件属主/属组的用户 u1 授予 rwx 的 ACL 权限,并验证 u1 能否修改文件。

参考答案:

# 1. 在根目录创建权限为 775 的 acl 目录
sudo mkdir /acl
sudo chmod 775 /acl
# 2. 在其中创建权限为 770 的文件
sudo touch /acl/1_acl.txt
sudo chmod 770 /acl/1_acl.txt
# 3. 给 u1 添加 rwx 的 ACL 权限
sudo setfacl -m u:u1:rwx /acl/1_acl.txt
# 4. 查看 ACL 与权限位末尾的 + 标记
getfacl /acl/1_acl.txt
ls -l /acl/1_acl.txt
# 5. 切换到 u1 尝试修改文件(应成功)
su - u1
echo "test" >> /acl/1_acl.txt

要点:文件权限 770 使其他用户本无任何权限,ACL 的命名用户条目在「所属组」之前被匹配,因此 u1 获得了 rwx;ls -l 权限位末尾会出现 +。


十三、扩展思考

  1. 了解 Linux 高级文件权限体系,掌握以下命令:setfacl、getfacl、chattr、lsattr、getenforce、setenforce。其中 getenforce/setenforce 用于查看和临时切换 SELinux 的强制模式(Enforcing/Permissive/Disabled),SELinux 是在 DAC(自主访问控制)之上的 MAC(强制访问控制)机制。
  2. ls -l 列出的文件信息存放在什么地方? 存放在文件的 inode(索引节点)中,包括文件类型、权限、链接数、UID、GID、大小、时间戳和数据块指针;文件名不在 inode 中,而在目录项里。
  3. 目录也是文件,目录里面存放的是什么内容?目录里文件的数据存放在目录里吗? 目录的数据块中存放的是「文件名 → inode 号」的映射表(目录项),并不存放文件本身的数据;文件数据存放在各自 inode 指向的数据块中。
  4. 文件的 link 数目代表什么?删除文件操作和这个数目有什么关系?当数目减到零时会发生什么? link 数是指向该 inode 的硬链接(目录项)数量。rm 实际是删除一个目录项并把链接数减 1;当链接数减到 0 且没有进程打开该文件时,inode 与数据块才被真正释放。
  5. 获取一个文件的文件名需要什么权限? 需要对其所在目录有 r 权限(读取目录项)。
  6. 获取文件的大小、所有者、时间等元数据信息需要什么权限? 需要对其所在目录有 x 权限(用于解析路径、读取 inode),仅有 r 只能看到文件名而看不到详细属性。

十四、命令速查表

用户与组

操作 命令
创建用户 useradd <user> / adduser <user>
创建用户并指定主组 useradd -g <group> <user>
设置密码 passwd <user>
删除用户 userdel -r <user>
切换用户 su - <user>
查看用户信息 id <user>
查看在线用户 who / w
修改 UID usermod -u <UID> <user>
修改 GID(主组) usermod -g <GID> <user>
追加附加组 usermod -aG <group> <user>
修改家目录 usermod -d <dir> <user>
修改登录 Shell usermod -s <shell> <user>
修改用户名 usermod -l <new> <old>
锁定用户 passwd -l <user> / usermod -L <user>
解锁用户 passwd -u <user> / usermod -U <user>
查看密码策略 chage -l <user>
强制下次登录改密码 chage -d 0 <user>
创建组 groupadd <group>
删除组 groupdel <group>
修改组 GID groupmod -g <GID> <group>
添加用户到组 gpasswd -a <user> <group>
设置组管理员 gpasswd -A <user> <group>
查看所属组 groups [user]
临时切换有效组 newgrp <group>

权限

操作 命令
修改权限 chmod 755 <file>
符号方式修改 chmod u+x,g+r,o-r <file>
递归修改权限 chmod -R 755 <dir>
修改属主/属组 chown <user>:<group> <file>
仅修改属组 chgrp <group> <file>
递归修改属主 chown -R <user>:<group> <dir>
查看/设置掩码 umask / umask 0022
设置 SUID chmod u+s <file>
设置 SGID chmod g+s <dir>
设置 Sticky chmod o+t <dir>
设置 ACL setfacl -m u:<user>:rwx <file>
递归设置 ACL setfacl -Rm u:<user>:rwx <dir>
查看 ACL getfacl <file>
清除全部 ACL setfacl -b <file>
设置不可变属性 chattr +i <file>
设置只追加属性 chattr +a <file>
查看隐藏属性 lsattr <file>

十五、注意事项

  1. root 用户的 UID 必须为 0,且系统中应保持唯一。
  2. 删除用户建议使用 userdel -r,避免残留家目录和邮件文件。
  3. 修改用户家目录前务必备份数据,并确保用户已登出和被锁定。
  4. 新建用户默认无密码(CentOS),必须用 passwd 设置后才能登录;切勿用清空 /etc/shadow 密码字段的方式实现免密。
  5. 对公共目录授 w 权限需特别谨慎,建议配合 Sticky 位使用;公开目录权限不要超过 755。
  6. sudoers 文件务必使用 visudo 编辑,以避免语法错误导致无法提权;命令须写绝对路径。
  7. usermod -G 会覆盖原有附加组,追加请务必使用 -aG;gpasswd -A/-M 同样是覆盖语义。
  8. 不能删除某用户的主组,需先删除该用户。
  9. ACL 权限在跨分区复制时可能丢失,重要文件建议使用 cp -p;CentOS 6 的新分区可能需要手动开启 ACL,CentOS 7 的 XFS 默认已启用。
  10. chattr +i 可以阻止包括 root 在内的所有用户直接修改或删除文件,但并非绝对不可逆:root(具备 CAP_LINUX_IMMUTABLE 权限)仍可执行 chattr -i 解除后再操作,因此它是「防误操作」手段,不能当作安全边界;解除前请确认业务影响。
  11. umask 的正确算法是「默认权限 AND (NOT umask)」,不要用异或或减法。
  12. 给 cat、vim 等通用命令加 SUID/SGID 属于极高危操作,实验后必须立即恢复。
最后修改:2026 年 09 月 20 日
如果觉得我的文章对你有用,请随意赞赏