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–999Ubuntu: 100–999 |
默认不允许登录系统,用于给服务提供运行时的身份 |
| 普通用户 | CentOS:1000–60000Ubuntu: 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 可禁止登录) |
迁移(移动)用户家目录的一般步骤
当用户家目录所在设备空间不足时,可按下述步骤迁移:
- 预备一个有足够空间的存储设备,并完成挂载。
- 确保该用户已经登出。
- 暂时禁用该用户:
sudo passwd -l <username>。 - 把用户的家目录移动(或复制)到新位置。
- 在
/etc/passwd中修改对应用户的第 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 密码的处理思路
-
在登录页面进入 GRUB 修改启动参数、进入单用户模式重置密码(需物理/控制台访问权限)。
-
如果还记得一个具有 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 变量所保存目录中的命令。
授权流程
-
切换到 root(或具有修改
/etc/sudoers权限的用户):su root # 或 sudo -i -
编辑 sudo 配置(推荐使用
visudo,它会进行语法检查):visudo # 或 vim /etc/sudoers -
添加授权规则。
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 权限判断顺序
- 先判断是否为文件的所有者;若是,执行所有者(u)权限后结束。
- 若不是所有者,判断是否属于文件所属组(主组或附加组均可);若是,执行所属组(g)权限后结束。
- 若都不是,执行其他人(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 目标用户、免密与需密码两类),并逐条验证。
参考答案:
- 创建用户:
sudo useradd u1
sudo useradd u2
- 通过
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
- 验证:
# 指定目标用户执行,否则默认以 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,并保证用户能正常登录使用。
参考答案(步骤):
- 预备一个有足够空间的存储设备并挂载。
- 确保该用户已经登出。
- 暂时禁用用户:
sudo passwd -l u1。 - 将家目录移动或复制到新位置。
- 修改
/etc/passwd中对应用户的第 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:无密码登录
题目:用两种方法实现用户无密码即可登录。
参考答案:
- 修改
/etc/passwd:将对应用户第 2 列的x删除(该字段留空)。 - 修改
/etc/shadow:将对应用户第 2 列的加密密码内容删除(保留冒号分隔符)。
安全警告:空密码意味着任何人都能以该用户身份登录,属于严重安全风险,仅可用于实验环境,生产环境严禁使用。禁止密码登录应使用
passwd -l锁定。
PPP8:两种方法给用户改名
题目:用两种方法把用户改名。
参考答案:
- 使用命令:
sudo usermod -l <newname> <oldname>。 - 直接修改配置文件:编辑
/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(全部所属组)作用于访问文件时的权限匹配。
参考答案(步骤):
- 创建组
g1、g2和用户u1。 - 将
u1加入g1和g2,并将g1设为默认有效组(主组)。 - 以
u1登录并创建文件,ls -l查看属组,应为g1。 - 执行
newgrp g2切换有效组,再创建文件,对比属组,应为g2。 - 验证
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:组管理员是否可以不属于该组
题目:验证一个不属于某组的用户能否被设置为该组的管理员。
参考答案(步骤):
- 创建组
g1和用户u1、u2、u3。 - 将
u1、u2加入g1。 - 尝试将不属于
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,体会特权位对身份的影响,并在测试后恢复原始权限。
参考答案(步骤):
- 用普通用户读取一个只有 root 可读的文件(如
/etc/shadow),观察结果(Permission denied)。 - 用 root 给
/bin/cat加上 SUID 位,再次用普通用户读取,观察结果(可以读取成功)。
sudo chmod u+s /bin/cat
su - u1
cat /etc/shadow
exit
- 恢复
/bin/cat的权限:
sudo chmod u-s /bin/cat
- 类似地,给
/bin/cat加 SGID 位并配合文件属组权限进行测试:
sudo chmod g+s /bin/cat
# 准备一个属组为特定组、组权限可读而其他人不可读的文件,用普通用户读取验证
sudo chmod g-s /bin/cat
- 测试完毕后务必恢复原始权限。
安全警告:给
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 权限位末尾会出现 +。
十三、扩展思考
- 了解 Linux 高级文件权限体系,掌握以下命令:
setfacl、getfacl、chattr、lsattr、getenforce、setenforce。其中getenforce/setenforce用于查看和临时切换 SELinux 的强制模式(Enforcing/Permissive/Disabled),SELinux 是在 DAC(自主访问控制)之上的 MAC(强制访问控制)机制。 ls -l列出的文件信息存放在什么地方? 存放在文件的 inode(索引节点)中,包括文件类型、权限、链接数、UID、GID、大小、时间戳和数据块指针;文件名不在 inode 中,而在目录项里。- 目录也是文件,目录里面存放的是什么内容?目录里文件的数据存放在目录里吗? 目录的数据块中存放的是「文件名 → inode 号」的映射表(目录项),并不存放文件本身的数据;文件数据存放在各自 inode 指向的数据块中。
- 文件的 link 数目代表什么?删除文件操作和这个数目有什么关系?当数目减到零时会发生什么? link 数是指向该 inode 的硬链接(目录项)数量。
rm实际是删除一个目录项并把链接数减 1;当链接数减到 0 且没有进程打开该文件时,inode 与数据块才被真正释放。 - 获取一个文件的文件名需要什么权限? 需要对其所在目录有
r权限(读取目录项)。 - 获取文件的大小、所有者、时间等元数据信息需要什么权限? 需要对其所在目录有
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> |
十五、注意事项
- root 用户的 UID 必须为
0,且系统中应保持唯一。 - 删除用户建议使用
userdel -r,避免残留家目录和邮件文件。 - 修改用户家目录前务必备份数据,并确保用户已登出和被锁定。
- 新建用户默认无密码(CentOS),必须用
passwd设置后才能登录;切勿用清空/etc/shadow密码字段的方式实现免密。 - 对公共目录授
w权限需特别谨慎,建议配合 Sticky 位使用;公开目录权限不要超过755。 sudoers文件务必使用visudo编辑,以避免语法错误导致无法提权;命令须写绝对路径。usermod -G会覆盖原有附加组,追加请务必使用-aG;gpasswd -A/-M同样是覆盖语义。- 不能删除某用户的主组,需先删除该用户。
- ACL 权限在跨分区复制时可能丢失,重要文件建议使用
cp -p;CentOS 6 的新分区可能需要手动开启 ACL,CentOS 7 的 XFS 默认已启用。 chattr +i可以阻止包括 root 在内的所有用户直接修改或删除文件,但并非绝对不可逆:root(具备CAP_LINUX_IMMUTABLE权限)仍可执行chattr -i解除后再操作,因此它是「防误操作」手段,不能当作安全边界;解除前请确认业务影响。umask的正确算法是「默认权限 AND (NOT umask)」,不要用异或或减法。- 给
cat、vim等通用命令加 SUID/SGID 属于极高危操作,实验后必须立即恢复。
此处评论已关闭