简介
Linux 是一种多用户操作系统。每个进程和文件都属于某个用户,每个用户都有一个主组,还可以加入任意数量的附加组。身份、所有权和权限位共同决定谁可以读取、修改、执行或进入某个资源。
在本实验中,你将使用专用练习账户搭建一个小型团队环境。你将创建用户、管理组成员关系、保护文件、检查账户锁定状态,使用 umask 控制默认权限,并配置带粘滞位和 setgid 的目录。所有操作都在实验环境中完成,不会改变默认的 labex 登录路径。
检查身份并创建练习用户
在本步骤中,你将检查当前身份,并创建一个用于权限练习的独立账户。Linux 使用用户名和数字用户 ID(UID)表示用户,同时记录主组 ID(GID)以及用户所属的附加组。
首先确认当前 shell 的身份:
whoami
输出应为 labex。接着显示此账户关联的 UID、主组和附加组:
id
具体数字 ID 可能不同,但输出会使用 uid、gid 和 groups 标出这些信息。
创建账户会修改系统文件,因此需要管理员权限。sudo 的含义是「以超级用户身份执行」:它会先检查当前账户是否有权限,然后以提升后的权限运行后面的命令。只对确实需要管理权限的命令使用 sudo,并在按下回车键前完整阅读命令。
下面的 useradd 命令使用了三个选项:
-m创建主目录。-U创建一个与用户名相同的主组。-s /bin/bash将 Bash 设置为该账户的登录 shell。
创建名为 jack 的练习用户:
sudo useradd -m -U -s /bin/bash jack
检查新账户及其主目录:
id jack
ls -ld /home/jack
id 输出应显示 jack 同时作为用户名和主组名。目录列表应显示 /home/jack 已存在,并且所有者和所属组为 jack:jack。
管理附加组
在本步骤中,你将创建团队组,并把用户加入附加组。用户的主组通常会成为新建文件的所属组。附加组则用于授予用户对其他共享资源的访问权限。
创建名为 developers 的组:
sudo groupadd developers
usermod -aG 选项表示「追加到附加组」。其中 -a 很重要:如果不使用它,-G 可能会替换用户现有的附加组成员关系。将 jack 加入 developers 和 sudo:
sudo usermod -aG developers,sudo jack
同时将 labex 加入 developers。当前 shell 不会立即获得新的组身份;你将在最后一个步骤中安全地刷新它。
sudo usermod -aG developers labex
检查两个账户:
groups jack
groups labex
第一条命令的输出应包含 jack、developers 和 sudo。第二条命令的输出应包含 developers。加入 sudo 后,经过身份验证的账户可以请求提升权限;该权限只能授予可信的管理员。
控制文件所有权和权限
在本步骤中,你将为团队报告设置指定的所有者、所属组和权限模式。长格式列表会先显示文件类型,随后显示分别对应所有者、所属组和其他用户的三组权限。
在项目目录中创建一个空报告文件:
touch /home/labex/project/secure-report.txt
使用 chown 的 user:group 格式同时修改所有者和所属组:
sudo chown jack:developers /home/labex/project/secure-report.txt
设置权限模式 640:
sudo chmod 640 /home/labex/project/secure-report.txt
在数字表示法中,读取权限为 4,写入权限为 2,执行权限为 1。因此:
- 所有者的
6表示可读和可写(4 + 2)。 - 所属组的
4表示只读。 - 其他用户的
0表示没有访问权限。
检查结果:
ls -l /home/labex/project/secure-report.txt
stat -c 'owner=%U group=%G mode=%a' /home/labex/project/secure-report.txt
稳定的 stat 字段应报告 owner=jack group=developers mode=640。
检查并修改账户锁定状态
在本步骤中,你将练习临时锁定和解锁专用账户。Linux 会将密码哈希和账户状态存储在 /etc/shadow 中。密码字段开头的 ! 表示密码身份验证已锁定。
实验环境已创建名为 contractor 的练习账户。只显示其密码字段的第一个字符,避免输出密码哈希本身。从左到右阅读这条管道命令:getent shadow contractor 获取该账户的 shadow 记录;第一个 cut 使用 : 作为分隔符并选择第 2 个字段;第二个 cut 保留该字段的第 1 个字符:
sudo getent shadow contractor | cut -d: -f2 | cut -c1
初始字符通常应为 $,这是现代密码哈希格式的开头。使用 usermod -L 锁定账户:
sudo usermod -L contractor
再次检查第一个字符:
sudo getent shadow contractor | cut -d: -f2 | cut -c1
现在应为 !。使用 usermod -U 解锁账户,并确认 ! 已消失:
sudo usermod -U contractor
sudo getent shadow contractor | cut -d: -f2 | cut -c1
在本场景中,contractor 已离开团队。最后再次锁定该账户,同时保留其文件:
sudo usermod -L contractor
锁定密码身份验证不会删除账户,也不会删除其主目录,并且不一定会终止现有会话。这与删除用户不同;当需要保留文件供后续检查时,锁定账户非常有用。
使用 Umask 控制默认权限
在本步骤中,你将使用 umask 控制 shell 创建新文件和目录时要移除的权限位。程序通常以普通文件最大模式 666 和目录最大模式 777 开始。掩码 027 会移除所属组的写权限,以及其他用户的全部权限。
为实验创建工作区:
mkdir -p /home/labex/project/umask-demo
保存当前掩码,以便稍后恢复。语法 $(command) 称为命令替换:shell 会运行括号中的命令,并将整个表达式替换为该命令的输出。赋值语句会把结果保存到 original_umask 中;和其他 shell 赋值一样,= 两侧不能有空格。
original_umask=$(umask)
应用掩码 027,然后创建一个文件和一个目录:
umask 027
touch /home/labex/project/umask-demo/private-note.txt
mkdir /home/labex/project/umask-demo/private-dir
检查生成对象的数字权限模式:
stat -c '%a %n' /home/labex/project/umask-demo/private-note.txt /home/labex/project/umask-demo/private-dir
文件的权限模式应为 640,目录的权限模式应为 750。文件不会自动获得执行权限。恢复 shell 原来的掩码:
umask "$original_umask"
修改 umask 只会影响之后创建的对象,不会改写现有对象的权限。
使用粘滞位保护共享目录
在本步骤中,你将配置一个公共投递箱,使所有人都能创建文件,但不能删除其他用户拥有的文件。普通模式 777 会授予所有用户对目录的完整访问权限。添加粘滞位后,目录中的删除规则会发生变化。
创建共享目录并设置模式 1777。开头的 1 用于启用粘滞位。
mkdir /tmp/shared-dropbox
chmod 1777 /tmp/shared-dropbox
使用 sudo -u,分别以两个练习账户的身份创建一个文件:
sudo -u jack touch /tmp/shared-dropbox/jack-note.txt
sudo -u contractor touch /tmp/shared-dropbox/contractor-note.txt
现在让 jack 尝试删除 contractor 的文件:
sudo -u jack rm /tmp/shared-dropbox/contractor-note.txt
这次失败是预期结果。你应看到 Operation not permitted,并且 contractor 的文件仍然存在。检查目录:
ls -ld /tmp/shared-dropbox
权限字符串应以小写 t 结尾,例如 drwxrwxrwt。小写 t 表示粘滞位和其他用户的执行权限都已设置。大写 T 表示已设置粘滞位,但对应的执行权限未设置。
配置 Setgid 团队目录
在本步骤中,你将准备一个私有协作目录。对目录设置 setgid 后,新创建的子对象会继承该目录的所属组,而不是创建者的主组。这样可以让团队文件始终关联到同一个共享组。
创建目录:
mkdir /home/labex/project/team-share
将 jack 设置为所有者,将 developers 设置为所属组:
sudo chown jack:developers /home/labex/project/team-share
设置模式 2770。开头的 2 用于启用 setgid;770 授予所有者和所属组完整访问权限,同时拒绝其他用户访问。
sudo chmod 2770 /home/labex/project/team-share
检查结果:
ls -ld /home/labex/project/team-share
stat -c 'owner=%U group=%G mode=%a' /home/labex/project/team-share
长格式列表应在所属组的执行权限位置显示 s,例如 drwxrws---。小写 s 表示 setgid 和所属组执行权限都已启用。大写 S 表示已设置 setgid,但所属组执行权限缺失。
Setuid 会在所有者执行权限位置显示 s,它是另一种特殊权限位,常见于经过严格控制的系统可执行文件。阅读权限时要能识别它,但不要将其添加到任意程序上。
刷新组成员关系并验证继承效果
在本步骤中,你将在子 shell 中激活 developers 成员关系,并验证 setgid 会控制新文件的所属组。将用户加入 /etc/group 不会更新已经运行的 shell 的附加组。
启动一个以 developers 为活动组的子 shell:
newgrp developers
命令提示符可能会刷新。你仍然是 labex 用户,但子 shell 现在将 developers 作为有效组。确认这两个身份:
id
在 setgid 目录中创建文件:
touch /home/labex/project/team-share/labex-note.txt
检查新文件:
stat -c 'owner=%U group=%G mode=%a' /home/labex/project/team-share/labex-note.txt
所有者应为 labex,所属组应为 developers。setgid 会继承所属组;文件的读写权限位仍取决于创建进程及其 umask。
退出子 shell,返回原来的终端会话:
exit
子 shell 关闭后,该文件仍会保留。
总结
你练习了 Linux 系统使用的核心身份与访问模型:创建用户和团队组、管理附加组成员关系、分配所有权,并将数字权限模式转换为实际的访问规则。你还在不暴露密码哈希的情况下检查了账户锁定状态。
随后,你进一步学习了普通权限之外的机制:umask 控制默认权限,粘滞位保护公共目录中的文件,setgid 在私有协作目录中保持团队组所有权。最后,你使用 newgrp 刷新组成员关系,并验证了真实文件继承的所属组。



