资讯动态

Linux用户与附加组管理:从概念到实战的10个案例

发布时间:2026/10/21 12:31:23 来源:尧图企业网站定制
Linux 用户、用户组与附加组是系统管理里绕不开的核心主题。很多人在刚接触 Linux 时会把注意力放在文件权限的 rwx 上却忽略了权限的归属主体——用户和组。实际上用户与组的配置直接决定了谁能登录系统、谁能访问某个目录、谁能执行某个需要特权的命令。这篇内容我打算把用户、用户组、附加组这几个概念串起来讲透再用 10 个实战例子把常见的操作场景覆盖一遍。每个例子都会附带验证方法和注意事项方便你直接照着操作。整套内容的定位是适合刚入门 Linux 的新手也适合已经会基本操作但没理清主组和附加组关系的进阶学习者。读完你应该能独立完成用户创建、组管理、组权限分配、批量用户处理等任务并且知道遇到权限问题时该从哪里排查。1. 先把概念厘清用户、UID/GID 与组的底层逻辑如果你已经用了一段时间 Linux可能知道useradd创建用户、usermod修改用户、groupadd创建组。但是很多教程只会告诉你“怎么用命令”不会告诉你“命令到底在系统里做了什么”。这导致的问题是一旦遇到非标准场景就不知道怎么排查了。1.1 用户条目到底存了哪些信息每个 Linux 用户都对应/etc/passwd文件中的一行记录。虽然文件名里有 password 这个词但实际密码哈希并不在这里密码通常在/etc/shadow文件中。/etc/passwd一行由 7 个字段组成用冒号分隔。举个实际例子webuser:x:1001:1001:Web Service User:/home/webuser:/bin/bash逐字段拆开看就是字段位置示例值含义1webuser用户名登录时使用的名称2x密码占位符x 表示密码哈希存放在 /etc/shadow31001UID用户 ID内核实际识别的是这个数字41001主组 GID用户主组的数字 ID5Web Service UserGECOS 字段通常是用户全名或备注信息6/home/webuser家目录路径7/bin/bash登录 Shell这里有一个容易忽略的知识点内核不认用户名只认 UID。你执行ls -l看到文件归属显示为webuser那只是系统把 UID 翻译成了名字而已。如果两个用户拥有相同的 UID那么在当前系统里这两个用户名会指向同一个身份文件的归属显示也可能出现混乱。所以在手动修改 UID 时务必确保全局唯一。组的信息存放在/etc/group文件中同样是一行多个字段webgroup:x:1001:alice,bob这一行的含义是组名 webgroup密码占位符 xGID 1001组成员是 alice 和 bob。注意第四列列出的成员指的是“把这个组作为附加组”的用户。如果某个用户的主组就是这个组那么该用户不会出现在这一列因为主组成员关系已经从/etc/passwd的第四个字段体现了。1.2 主用户组与附加组的本质区别很多人在这里开始犯迷糊。我见过不少初学者用usermod -g group1 user1想给用户加组结果发现用户原来的主组被换掉了甚至某些文件的组归属也发生了变化。主用户组primary group是用户“默认”的组归属。用户创建文件时文件所属组默认取用户的当前主组。每个用户有且仅有一个主组。附加组supplementary groups是用户额外加入的组用户可以有零个或多个附加组。附加组的主要作用是赋予用户访问特定资源的权限。比如用户 alice 是开发组成员又是运维组成员但她最终登录 Shell 时当前有效组 ID 仍然是主组 ID。只有当某个文件或目录的组权限被设置为开发组或运维组可访问时alice 才能通过附加组身份获得相应权限。用一个通俗类比来理解主组相当于你的“默认部门”你写的工作文档自动盖上这个部门的章附加组相当于你“兼任的其他部门”那些部门的会议室和资料室也对你开放但你日常办公还是在自己的默认部门。下面这个例子能很直观地反映主组和附加组的区别# 创建一个测试用户并查看其组信息 useradd -m -d /home/alice -s /bin/bash alice id aliceid alice的输出是这样的uid1001(alice) gid1001(alice) groups1001(alice)这里gid后面跟的是当前有效主组groups后面列出的是用户所属的所有组。因为此时 alice 还没有附加组所以 groups 里面只有 alice 组。然后我们给 alice 添加一个附加组groupadd devops usermod -aG devops alice id alice输出变成了uid1001(alice) gid1001(alice) groups1001(alice),1002(devops)注意gid仍然是 1001没有变但 groups 列表里多了一个 devops。这说明-aG只追加附加组不会影响主组。如果你用了usermod -G devops alice没有 -aalice 原来的附加组会被清空只保留 devops。细节很重要。-a的意思是 append追加-G表示设置附加组列表。两者结合才是“追加附加组”单独-G是“覆盖附加组列表”。很多线上事故都是因为少了-a导致用户丢失了原有附加组突然无法访问某个共享目录。2. 三剑客解析useradd、usermod、groupadd 的设计逻辑与选择掌握了文件层面的原理之后理解命令的设计逻辑就水到渠成了。Linux 用户管理命令有很多但实际高频使用的就那三四个。我按使用频率和重要程度来拆一下。2.1 三剑客的能力边界对照表命令主要用途常用参数注意事项useradd创建新用户-m创建家目录、-d指定家目录、-s指定 Shell、-G附加组、-u指定 UID不加 -m 可能不创建家目录不同发行版默认策略不同usermod修改已有用户属性-aG追加附加组、-g修改主组、-l改名、-L锁定用户-G 不带 -a 会覆盖附加组列表groupadd创建新用户组-g指定 GID、-r创建系统组系统组通常用于服务账号GID 小于 1000gpasswd管理组成员-a添加成员、-d删除成员、-M设置成员列表也可以用来设置组密码但工作中较少用userdel删除用户-r连同家目录和邮件目录一起删除不删家目录会留下残留文件UID 可能被复用后产生归属错乱这个表格里usermod -aG是最容易出现误操作的一对参数。我见过有人写脚本批量给用户加附加组时漏掉-a最后所有用户的附加组都被重置成了同一个组排查了很久才发现是参数少了一个字母。运维工作里“小细节产生大故障”的典型案例就是这么来的。2.2 为什么id是验证配置的第一利器配置完用户和组之后第一件事就是验证。验证用户组关系id命令是最直接的id 用户名它会显示 uid、gid主组、groups全部组。groups 用户名也能列出该用户所属的全部组但格式比id略简陋。排查问题时我一般先跑id确认用户实际归属的所有组是否符合预期。如果预期有两个附加组但id只显示一个那就是添加附加组时没有用-a把之前的覆盖掉了。这类问题用id一眼就能定位。系统里还有一些“看起来是用户但其实是服务账号”的特殊条目比如nobody、www-data、systemd-network等。这些账号通常没有家目录也没有登录 Shell/usr/sbin/nologin或者/bin/false它们的存在是为了让某个服务以受限权限运行。你想用su切换到这些账号时通常会失败这是正常的因为它们被刻意设计为不可登录。理解这一点看到/etc/passwd里一堆奇怪账号时就不会慌。3. 10 个实战例子从单命令操作到批量处理这个部分是整篇内容的重点。我把 10 个例子分成两组第一组是核心操作类覆盖日常最常用的用户和组操作第二组是进阶场景类覆盖多用户协作、批量处理和特殊场景配置。3.1 核心操作类账号与组的基础配置例子 1创建用户并设置主组与附加组先看需求某公司新增了一名开发者需要创建账号devel01主组为developers附加组为docker和sudo。# 先创建组如果不存在的话 groupadd developers groupadd docker # 创建用户同时设置主组和附加组一次完成 useradd -m -d /home/devel01 -s /bin/bash -g developers -G docker,sudo devel01 # 验证 id devel01输出会显示uid1002(devel01) gid1001(developers) groups1001(developers),1002(docker),27(sudo)这里有两个细节。第一-g和-G同时使用时-g指定主组-G指定附加组列表多个附加组用逗号分隔不要加空格。第二-m和-d可以组合使用-d指定家目录路径-m表示如果目录不存在则创建。如果只给-d不给-m家目录不会自动创建用户登录后可能连 HOME 目录都没有虽然不一定报错但很多程序会表现异常。例子 2修改用户主组场景某员工从 A 团队调到了 B 团队需要把主组从team_a改为team_b。usermod -g team_b user_name执行后该用户的主组立即变为 team_b。这里要提醒一个容易被忽略的影响这个用户之后新建文件的默认所属组会变成 team_b但已经存在的文件不会自动改变组归属。如果他的旧文件也需要迁移归属通常得用find配合chown批量处理find /home/user_name -group team_a -exec chown :team_b {} \;这条命令把所有属于 team_a 组的文件改成 team_b 组。不过执行前最好确认你想改的范围别把不该动的文件也改了。例子 3追加附加组老生常谈的 -a 教训场景当前用户alice需要临时加入project_x组才能访问某个共享目录同时不能丢失她已有的附加组。usermod -aG project_x alice注意如果你写成usermod -G project_x alicealice 原有的附加组会被全部清空只保留 project_x。这个操作非常危险特别是当原有附加组中包含 sudo 或 docker 这类特权组时相当于直接移除了用户的管理和容器操作权限。我个人的习惯是所有涉及-G的场景一律写成-aG即使在“我知道用户当前只有一个附加组”的情况下也保持这个习惯。因为你可能搞不清用户被抓之后是否又有别人手动改过。宁可多花一个字母也不要冒失配风险。例子 4将用户从附加组中移除反向操作同样常见。某员工离职后需要从公司的共享协作组中移除但保留登录账号和家目录。gpasswd -d alice project_x执行后验证id alice确认 project_x 不再出现在 groups 列表中。gpasswd -d也可以换成usermod -G重新列附加组的方式移除但gpasswd -d更精确只操作一个组不会影响其他成员关系推荐优先使用。例子 5查看组内成员列表想看看developers组里都有谁最直接的方式是查看/etc/groupgetent group developers输出类似developers:x:1001:alice,bob,charlie但这里的第四列只显示“把 developers 作为附加组”的用户。如果某些用户的主组就是 developers他们是不会出现在这一列里的。想拿到完整成员列表得写个综合查询awk -F: $41001 {print $1} /etc/passwd; awk -F: $1developers {print $4} /etc/group | tr , \n思路是先从/etc/passwd中找出主组成员再取/etc/group中附加组成员两者合并才是真正完整的组内成员列表。实际工作中如果不需要区分主组和附加组可以简单点让所有人把 developers 作为附加组加入这样getent group developers就能一网打尽。3.2 进阶场景类从单机管理到协作配置例子 6批量创建用户并设置统一附加组某公司准备上线一个模拟项目 X需要一次性创建 5 个账号proj01到proj05并且都加入project_x组主组用project_x。# 先创建组 groupadd project_x # 循环创建用户 for i in $(seq -w 1 5); do useradd -m -d /home/proj$i -s /bin/bash -g project_x -G project_x proj$i doneseq -w 1 5输出01 02 03 04 05然后拼接出 proj01 到 proj05。这个脚本里我刻意把-g和-G都设成了 project_x这样用户在/etc/passwd中的主组是 project_x同时/etc/group中也会列出该用户方便使用getent group project_x直观查看完整成员。循环操作完成后用一条命令验证id proj01 proj02 proj03 proj04 proj05批量操作里最常犯的错是用户名生成逻辑和预期不符。比如想生成proj1到proj5但脚本写错用seq -w会带前导零想生成带前导零却漏了-w。建议先单独跑一下seq看看输出再执行后面的循环别在批量命令写完就裸奔。例子 7删除用户并完整清理文件删除用户时如果不加-r用户的家目录和邮件目录会残留时间长了可能积累大量孤儿文件。正确做法userdel -r proj01这条命令会删除用户和它的家目录、邮件目录还会顺带清理/etc/passwd、/etc/shadow、/etc/group中的相关条目。但注意userdel -r并不能删除该用户在其他目录下拥有的文件。如果用户此前在/tmp或/var/data下创建过文件这些文件依然存在且由于 UID 被删除ls -l显示的将是数字 UID 而不是用户名。这种情况可以使用find扫描并处理find / -user 1002 2/dev/null把输出核对一遍再决定是删除还是chown给其他用户。强烈建议不要直接删掉所有输出因为可能有些文件属于系统关键路径盲目删除会引发别的故障。例子 8创建服务账号并禁用登录某 Web 服务需要专属账号运行但这个账号不能用于人肉 SSH 登录。服务账号的创建方式与普通用户有显著区别useradd -r -M -d /var/www/webapp -s /usr/sbin/nologin webapp参数解释-r创建系统账号UID 通常小于 1000不进入用户“正常”范围内。-M不创建家目录。服务账号通常不需要家目录而是在配置里指定工作目录。-d指定账号的主目录路径这里指向/var/www/webapp。-s /usr/sbin/nologin禁止该账号登录 Shell。如果服务账号后续被某些不该用的工具调用提示This account is currently not available这并不是报错而是 nologin 的效果。有些运维新手看到这个提示就以为系统出问题了其实是账号被刻意锁定了登录路径。例子 9临时锁定用户而不删除某些情况下员工出差、项目暂停账号需要保留但不能登录。锁定用户的方式有两种一种是锁定密码一种是锁定账号本身。# 锁定密码 passwd -l username # 锁定账号usermod 方式 usermod -L username两者效果略有差异但核心目标都是禁止密码登录。被锁定的用户如果用 SSH 公钥登录公钥认证此时通常仍然有效所以如果目标是彻底禁止登录还需要禁用公钥认证或修改其登录 Shell 为 nologinusermod -s /usr/sbin/nologin username解除锁定passwd -u username或者usermod -U username账号锁定是运维里非常常用的操作但很多人只在文档里看到过没有认真区分“锁定密码”和“禁用登录”的边界。我建议根据业务需求来决定用哪一个只是临时不让密码登录用passwd -l要完全禁止该账号一切登录直接usermod -s /usr/sbin/nologin。例子 10克隆用户配置并保留组关系场景某开发者要离职交接新接手者希望复用原账号的完整权限配置包括所有附加组。思路是先把原用户的附加组列表复制下来再用这些组创建新用户。# 获取原用户的附加组列表过滤掉主组 OLD_USERold_dev NEW_USERnew_dev OLD_GROUPS$(id -nG $OLD_USER | tr , | sed s/\b$OLD_USER\b//g | sed s/,,*/,/g;s/^,//;s/,$//) # 创建新用户主组沿用原用户主组附加组用复制来的列表 PRIMARY_GROUP$(id -ng $OLD_USER) useradd -m -d /home/$NEW_USER -s /bin/bash -g $PRIMARY_GROUP -G $OLD_GROUPS $NEW_USER这里id -nG $OLD_USER列出所有组名tr ,把空格换成逗号再用sed去掉原用户名对应的组因为用户名和主组同名时该组名会出现在附加组列表里属于冗余信息。这个脚本看起来繁琐但我在实际批量交接账号时经常这么用。如果嫌sed链太长容易出错也可以手动id看一下原用户的附加组再手写-G参数。10 个以下用户的场景手动其实更快。4. 组与权限的联动机制为什么“加了组”还是没权限操作层面熟悉之后必须补上权限联动这块知识。很多人明明把用户加到了正确的组结果访问目录仍然被拒问题往往出在文件系统的 ACL、目录权限、拥有者设置这些环节。4.1 读、写、执行与组成员身份的关系Linux 文件权限分三组属主权限、属组权限、其他人权限。每个位置用rwx表示r是读w是写x是执行。目录上的x比较特殊它表示“能否进入该目录”以及“能否访问目录内文件的元数据”。当用户访问一个文件时系统按顺序判断如果用户是文件属主按属主权限执行。如果用户不是属主但是文件属组的成员按属组权限执行。如果都不是按其他人权限执行。注意这个判断是“先到先得”。如果用户是属主即使属主权限没有任何 rwx系统也会直接拒绝并结束判断绝对不会继续看属组权限。这个逻辑非常重要它解释了“为什么用户明明在组里却无权访问”因为该用户恰好是这个文件的属主而文件对属主的权限设成---了。这种情况下用户作为属主都进不去自然更不可能靠附加组来“救”他。实际中这种场景不多但我在教学中见过有人把某个文件的属主改成了 root然后给开发组加了rwx权限结果开发用户访问时因为文件属主是 root开发用户不是 root所以走的是属组权限这才能够访问。如果你把文件属主写错了比如把“创建该文件的用户名”填到了另一个用户名上那所有非属主用户都会落到“其他人”权限而不是“属组”权限看起来“加了组”也白搭。4.2 虚拟项目的权限落地实战拿一个典型的共享协作场景来演示完整链路。假设你有一个共享目录/srv/teamshare要让team_a和team_b两个组的成员都能读写同时禁止其他人访问。# 创建目录 mkdir -p /srv/teamshare # 设置属组为 team_a chown root:team_a /srv/teamshare # 设置权限属主 root 全部权限属组 team_a 读写执行其他人无权 chmod 770 /srv/teamshare现在 team_a 组成员能访问但 team_b 组成员不能访问。要让 team_b 也能访问有两个办法。办法一把 team_b 的用户逐个加入 team_a 组。缺点成员管理混乱team_b 的用户从此有了 team_a 对所有资源的权限。办法二用 setgid 位 多组容器的思路把共享目录的组设成一个中立的组groupadd share_users usermod -aG share_users user_a1 usermod -aG share_users user_b1 chown root:share_users /srv/teamshare chmod 2770 /srv/teamsharechmod 2770中的2是 setgid 位。setgid 的效果是任何用户在这个目录下新建的文件和子目录其属组会自动继承该目录的属组share_users而不是用户的主组。这样就不怕用户建文件时把组归属弄乱了。验证 setgid 是否生效ls -ld /srv/teamshare输出中权限位如果是drwxrws---s就表示 setgid 已生效。这个时候team_a 的用户和 team_b 的用户都通过附加组share_users获得了访问权限。他们的主组没变但附加组统一了文件读写也能共享。还有一点要提如果目录下挂载了 NFS 或者使用了 ACL情况会更复杂。比如某目录设置了 ACL 白名单但你的用户是通过附加组加入的ACL 的匹配规则优先看用户本身再看用户所属组。如果 ACL 没有覆盖到正确组即使普通权限看起来没问题也可能被 ACL 拒绝。总之遇到权限问题时先用getfacl看看有没有默认 ACL 和扩展 ACL 在干扰。5. 高频问题与排查技巧实录遇到权限问题先别抓瞎最后一部分把我工作里经常遇到的用户和组相关问题汇总一下做成速查表形式。这些问题看起来五花八门但根源通常集中在几个点。现象可能原因排查方法useradd 报错用户名已存在、家目录冲突、UID 冲突查看 /etc/passwd 和当前用户列表用户无法登录 SSH密码锁定、Shell 为 nologin、家目录权限异常检查 /etc/shadow、账号锁定状态、家目录 700 权限新创建的组在 id 里看不到当前会话缓存了组信息需要重新登录一次使用 newgrp 激活新组或退出重登chown 命令提示非法用户用户名不存在或拼写错误检查 /etc/passwd 是否存在该用户文件权限明明是 770还是打不开目录被 ACL 控制getfacl 查看 ACL/etc/passwd 中出现重复 UID手动改坏了用户条目梳理 UID 归属避免共用关键 UIDuserdel -r 后发现一堆无主文件用户在其他目录下也有文件find / -uid 原UID 逐个排查用户能访问共享目录但无法新建文件目录权限不是 2770缺 setgid 或属组不对检查目录权限位和属组用id定位问题是第一步。比如用户投诉访问不了某个共享路径你在服务端执行id username getfacl /path/to/shared/dir ls -ld /path/to/shared/dir这三条命令基本能看出 90% 的权限问题用户归属的组是否对口、目录的属组是否匹配、ACL 是否默认拒绝。如果还不够再用strace -e tracefile让用户复现一次操作看看系统在内核层面到底拒绝了哪个路径。再补充一个使用习惯层面的建议修改用户或组之前先备份关键文件。/etc/passwd、/etc/shadow、/etc/group这三个文件是整个用户体系的根基改之前用cp复制一份带时间戳的备份cp /etc/passwd /etc/passwd.bak.$(date %Y%m%d%H%M%S) cp /etc/shadow /etc/shadow.bak.$(date %Y%m%d%H%M%S) cp /etc/group /etc/group.bak.$(date %Y%m%d%H%M%S)如果改完发现不对劲直接恢复备份重新来。这个习惯成本极低收益却非常大特别是对刚开始接触用户管理的同学来说。如果你用的是某些发行版用户管理可能存在封装工具比如某些桌面系统有用户管理面板但底层逻辑还是这些文件。命令行掌握扎实了无论用什么管理工具心里都有底。最后再分享一个我自己的习惯每次配置完用户和组我都会顺手把id输出、getent group输出和操作时间一起记录到运维笔记里。后面排查问题、审计权限、交接工作的时候这些记录能省掉大量回忆时间。用户与组的配置说到底是围绕/etc/passwd、/etc/group、/etc/shadow这三个文件展开的。把底层逻辑想清楚命令用起来就是顺理成章的事。遇到权限问题时先看id再看属组最后查 ACL按顺序来基本都能在几分钟内定位到根源。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑