
1. 用户与组管理到底在解决什么问题先说结论用户与组管理是所有多用户操作系统最基础、也最容易被轻视的一道安全防线。我见过不少项目初期图省事全部人共用一个账号等到需要追责、隔离权限、清理环境的时候才发现当初偷的懒全都变成了坑。用户与组管理的核心目标只有三个身份识别、权限控制、审计追溯。说白了就是搞清楚“谁在用这台机器”、限制“这个人能碰什么”、记录下来“这个人做过什么”。抛开这些明确的使用需求“为什么必须用组而不是挨个授权”也是新手最容易想不通的地方。我用一句话解释组是权限的批量打包。假设你的项目里有四个开发、两个测试、一个运维如果不用组每来一个新同事你就得在十台机器上分别修改配置漏掉一台就埋下一颗雷。有了组只需要把新人加进对应的组所有机器上的权限自动同步生效。这个课题适合谁来读如果你是刚接手服务器或工作站的开发、测试、运维同学尤其是以前一直习惯用管理员账号一把梭的人这篇文章能把用户与组管理的底层逻辑和常见坑讲透让你后续管理再多机器都不慌。我会从底层机制讲到核心命令再给一套可以直接抄作业的实操流程最后是排错实录。我强烈建议你看完这篇文章后立刻去自己常用的那台 Linux 机器上跑几遍命令。用户管理这事儿,光看永远学不会亲手创建、修改、删除几个用户和组踩过几次错才算真正过关。2. 用户和组的底层机制UID、GID 与权限模型的打通2.1 三个核心配置文件先搞懂系统怎么记录身份用户与组管理表面上是一堆命令背后实际上是四个文本文件在驱动一切。强烈建议你不要把它们当成“神秘的系统内部文件”它们本质上就是普通的文本只不过格式固定、系统启动时就会读取。第一个是/etc/passwd。每一行代表一个用户账号字段之间用冒号分隔。我拆开讲一下用户名:密码占位符:UID:GID:描述信息:家目录:登录Shell看到那个x或者*了吗那就是密码占位符真正的密码哈希值根本不在这里而是放在了/etc/shadow。这个设计是历史包袱也是安全进步——早期系统真的把加密后的密码放在/etc/passwd里但该文件需要被所有进程读取比如ls -l要显示文件名属主如果密码哈希也藏在这里等于把保险柜钥匙贴在了保险柜门上。所以后来把密码挪到了只有管理员可读的/etc/shadow。第二个是/etc/group。格式如下组名:组密码占位符:GID:组成员列表组密码目前实际场景使用极少但需要知道它的存在。成员列表用逗号分隔注意这里有个细节如果某个用户的主组就是当前组那么/etc/group里的成员列表通常不会包含他因为主组的归属关系在/etc/passwd的 GID 字段里已经写清楚了。副组附加组才会出现在这里的成员列表中。第三个是/etc/shadow里面存的是真正意义上的密码哈希、最近修改时间、密码有效期、失效警告天数、宽限天数、账号失效日期、保留字段。这个文件属于可读性极差、但字段非常关键的典型。平时排查用户无法登录的问题八成要回到这个文件里找答案。2.2 UID 和 GID 的分配逻辑理解编号才能理解权限UID 和 GID 是用户与组在系统内部的唯一编号。Linux 内核在处理权限时只关心数字不关系名。你删掉一个用户之后如果直接新建一个同名用户系统会分配一个全新的 UID旧文件上的属主信息拿不到同名的新用户身上。系统对 UID 的划分大致遵循以下区间不同发行版略有差异0管理员账号拥有整个系统的绝对权限。1-999系统预留账号例如运行服务时使用的 Nobody、守护进程账号等。1000-65534普通用户可用的 UID 区间。65534通常映射为 nobody 用户用于匿名访问等无属主场景。理解这个区间划分的意义在于你在批量创建用户时如果手动指定 UID务必避开系统预留段。我见过有人图省事直接把用户 UID 指定为 600结果该用户的进程恰好在某些场景下被系统服务误判成同一身份引发隐蔽的权限越界问题。还有一个很容易忽略的概念叫LOGIN_DEFS它的位置在/etc/login.defs。这里定义了新建用户时 UID 的起始值、密码加密算法、有效期默认值等。很多管理员不知道改用户创建默认策略要动这个文件结果每次新建用户都要手动追加一堆参数。2.3 文件权限与属主用户与组存在的最终意义你可能会想搞这么多用户和组图什么图的是最终落实到文件权限上。Linux 文件权限模型包含三段权限属主权限、属组权限、其他用户权限每段又可细分为读、写、执行。执行ls -l时你看到的第三列是属主第四列是属组。内核判断一个进程能否访问某个文件遵循一条简洁的规则如果进程有效的 UID 等于文件的属主 UID应用属主权限段否则如果进程有效的 GID 或任一附加组的 GID 等于文件的属组 GID应用属组权限段否则应用其他用户权限段。这里有一个常见的认知偏差以为“只要我是文件属组的一员就能享受属组权限”。实际上内核只认 GID如果你的身份在文件属组的 GID 里匹配不上哪怕人类肉眼看不出区别权限也一样不生效。所以排查权限问题时第一件事是执行id命令确认当前用户到底属于哪些组而不是盯着文件属性猜。文件权限的第三段还有一个粘滞位sticky bit和用户管理强相关。比如/tmp目录就是典型的drwxrwxrwt模式其中的t表示粘滞位。它的作用很简单在这个目录下只有文件属主、目录属主或管理员才能删除或重命名文件其他用户即使对该目录拥有写权限也不能动手删除别人的文件。这个机制在多用户共享目录的场景中非常关键我后面会结合实操细讲。3. 核心实操用户与组增删改查的常用命令与底层行为3.1 创建用户别只知道一个 useradd用户创建最核心的命令当然是useradd但这背后有一连串默认行为值得你逐条核实。不同发行版的useradd默认值差异很大。先看最基本的创建动作useradd dev01执行完之后发生了什么/etc/passwd增加一行/etc/shadow增加一行/home/dev01目录被创建/etc/skel里的骨架文件被复制进去同时一个与用户名同名的组也被建立。这里最容易被忽略的是/etc/skel目录。你希望每个新用户的家目录里自带某些公共文件比如.bashrc的定制版本、公司统一的 README 说明文件直接把文件丢进/etc/skel即可。我习惯把所有新用户都需要的基础配置放在里面省去后续逐个推送给用户的麻烦。创建用户时比较实用的参数组合useradd -m -d /export/home/dev01 -s /bin/bash -c 开发一组-张同学 dev01-m强制创建家目录即使系统默认值不允许也会创建。-d指定家目录路径不再用默认的/home/用户名。-s指定登录 Shell。如果设为/sbin/nologin用户无法直接登录常用于服务账号。-c注释信息建议写清楚人员身份或联系方式方便后续维护。为什么不建议不指定-m因为部分发行版在创建系统用户时默认不建家目录如果你误建了一个需要家目录的用户后续补目录还要手工设置权限和骨架文件平白多出一堆操作。3.2 修改与删除用户usermod 和 userdel 的边界问题修改用户属性时usermod是最顺手的工具。常见操作有usermod -aG docker dev01 usermod -s /bin/zsh dev01 usermod -L dev01 usermod -U dev01其中-aG两个参数必须一起使用。-G表示设置附加组列表如果不加-a系统会用新列表整体覆盖旧的附加组列表。我见过不止一次有人执行usermod -G docker dev01结果用户原本在sudo组里的身份直接被摘掉排查了半天才发现是覆盖问题。习惯性把-aG绑定在一起想能避免大量低级的权限事故。删除用户时userdel默认不删除家目录和邮件池。如果你确定要连人带目录一起清理userdel -r dev01这里要特别提醒删用户不等于删干净。用户的主组如果没有被任何文件引用会遗留为“孤儿组”用户曾经创建的目录和文件如果不在家目录里也会变成 UID 对应的无名文件。后面第五部分专门讲这个问题。3.3 用户组的管理命令和联动关系组管理的命令比较简洁groupadd ops groupdel ops groupmod -n newname ops但有一个非常关键的细节容易被忽视主组不能直接删除。如果某个用户当前的登录主组/etc/passwd里设置的 GID是某个组直接执行groupdel会报错。你得先修改用户的 GID 主组或者删除该用户再执行组删除。此外当一个组被删除时系统不会自动把该组曾经拥有的文件权限回收掉。那些文件的属组 GID 依然存在但/etc/group中已经没有对应的组名了。你用ls -l查看时会看到该文件属组变成一个数字 GID。这个数字如果不巧被后来新建的某个组占用那么新组会自动获得这些文件的属组权限隐蔽性极强也极具风险。我在生产环境清理历史遗留文件时专门用一条命令排查这类数字属主find / -nouser -o -nogroup 2/dev/null3.4 密码管理passwd 和 chage 联合使用用户创建后第一件事就是设密码passwd dev01但密码安全除了“设置时足够强”还要关注有效期。chage命令专门管理密码老化策略chage -M 90 dev01 chage -W 7 dev01 chage -E 2025-12-31 dev01-M 90密码最长使用 90 天。-W 7提前 7 天开始警告。-E 2025-12-31账号在指定日期失效适用于临时外包人员、学生账号。如果想查看一个用户的完整密码策略chage -l dev01这个命令输出的信息包括上次修改时间、密码过期时间、账号失效时间等排错时非常有价值。我遇到过用户的密码明明还没到期但就是无法登录的情况最后用chage -l一查发现是管理员之前手动把账号失效日期设置在了昨天。4. 实战从零搭建一套多用户项目环境接下来我提供一个可以直接照着操作的多用户环境搭建流程。场景设定是这样的一个小型项目组里面有四名开发人员、一名运维、两名外部协作者外加一台跑服务的机器。所有人员共用一台 Linux 服务器需要做到权限隔离、按组授权、临时账号到期自动失效。4.1 用户与组结构规划动手之前先画好规划这是很多人跳过的步骤但恰恰最重要。我的划分方式如下开发主组devteam包含四名开发人员权限范围是/data/project下的代码读写。运维组ops包含一名运维权限范围包括日志目录和部署目录。外部协作者新建一个组external限制他们只能访问/data/shared目录中明确开放的文件。服务账号新建一个系统用户svc_app没有登录 Shell只用于跑后台进程。汇总成一张规划表组名用途成员家目录级别devteam开发主组dev01-dev04/data/projectops运维人员ops01/data/logs 与部署脚本目录external外部协作者ext01-ext02/data/sharedsvc_app服务运行账号无不需要家目录4.2 创建用户与组的完整命令序列按照规划逐步执行我先创建组再创建用户因为用户创建时可以直接指定主组。groupadd devteam groupadd ops groupadd external创建四名开发人员。这里我用统一的格式描述信息写上人员简称方便后续识别useradd -m -d /home/dev01 -g devteam -s /bin/bash -c dev01-张三 dev01 useradd -m -d /home/dev02 -g devteam -s /bin/bash -c dev02-李四 dev02 useradd -m -d /home/dev03 -g devteam -s /bin/bash -c dev03-王五 dev03 useradd -m -d /home/dev04 -g devteam -s /bin/bash -c dev04-赵六 dev04给运维人员创建账号并附加到 devteam 组方便临时协助排查代码问题useradd -m -d /home/ops01 -g ops -s /bin/bash -c ops01-运维端 ops01 usermod -aG devteam ops01外部协作者用-e指定账号失效日期这里设定为 90 天后useradd -m -d /home/ext01 -g external -s /bin/bash -e 2025-11-30 -c ext01-外包A ext01 useradd -m -d /home/ext02 -g external -s /bin/bash -e 2025-11-30 -c ext02-外包B ext02服务账号不创建家目录Shell 设为禁止登录useradd -r -s /sbin/nologin -c 应用服务账号 svc_app-r表示创建系统账号UID 会自动落在系统区间不会占用普通用户名额。这一步对强迫症很友好。执行完上面的命令后用id dev01和id ops01验证身份归属再检查/etc/passwd末尾五行和/etc/group的内容是否与规划一致。4.3 目录权限划分与粘滞位应用账号建好后开始设置目录权限。首先创建项目根目录mkdir -p /data/project /data/logs /data/shared设置目录属组chgrp -R devteam /data/project chgrp -R ops /data/logs chgrp -R external /data/shared设置目录权限chmod -R ugrwX,o-rwx /data/project chmod -R ugrwX,o-rwx /data/logs chmod -R ugrwX,o-rwx /data/sharedugrwX里的X是特殊参数表示只有对目录或已有执行权限的文件才赋予执行权限纯文本文件不会被误加执行位。这是我个人最推荐的一种授权方式兼顾功能与卫生。外部协作者存在一种特殊需求希望彼此能在共享目录下互相查看文件但不允许删除其他人的文件。这就是前面提到的粘滞位应用的典型场景chmod t /data/shared设置完成后ls -ld /data/shared可以看到类似drwxrwxrwt的输出。验证一下效果外部协作者 ext01 在/data/shared下创建一个文件再用 ext02 去删除系统会拒绝提示没有权限。这个机制保证了共享目录的稳定性避免有人手滑删了别人的工作成果。4.4 赋予部分用户 sudo 权限开发人员经常需要执行一些需要管理员权限的命令比如安装依赖包、重启服务等。不建议直接给管理员密码也不建议全给 sudo正确做法是给有需要的人加入一个 sudo 授权组。在大多数主流 Linux 发行版上属于wheel或sudo组的用户默认具备管理员提权能力。以sudo组为例usermod -aG sudo dev01 usermod -aG sudo ops01验证方法sudo -l -U dev01输出中如果列出了规则说明这个用户可以在本机执行 sudo。出于最小化原则外部协作者不要加入任何 sudo 相关的组。4.5 初始密码与首次登录强制改密在新环境里一个标准操作是让用户首次登录后必须改密码。实现方式chage -d 0 dev01-d 0表示把密码最近修改时间设为 1970-01-01系统会认为密码已经过期强制用户在下次登录时立即修改新密码。这个机制比“手动告诉用户改密码”可靠得多它可以防止用户在不知道自己密码的情况下长期使用已知初始密码。批量执行可以写一个循环for u in dev01 dev02 dev03 dev04 ops01; do chage -d 0 $u done这条循环把 5 个用户全部设为首次登录强制改密。从安全角度看这比让用户带着初始密码用一个月强太多。5. 常见问题与排查技巧实录5.1 用户被锁定到底是谁动了密码文件现象用户反映无法登录系统提示密码错误次数过多或账号已锁定。排查路径分两条第一步检查账号是否被passwd -L锁定。执行passwd -S dev01查看状态如果输出中显示L开头说明被锁。解锁usermod -U dev01第二步查看/etc/shadow中该用户的密码哈希前缀。密码哈希字段如果以!开头表示该账号的密码处于锁定状态。很多发行版在用户创建但未设置密码时写入的占位符就是!此时登录是不可能成功的。第二种原因是多次输错密码触发了pam_faillock或类似机制的锁定。这类锁定的排查要看日志常见位置是/var/log/secure或/var/log/auth.log。定位到具体条目后可以用系统命令重置失败计数不同发行版略有区别整体思路是删除或重置该用户的失败记录。我特别想提醒不要动不动就“重置密码”来解决问题。先明确是哪种锁定如果是安全策略触发的临时锁定重置密码并不能解决根本问题用户继续输错旧密码照样会被再次锁定。5.2 删除用户后留下一堆数字属主文件场景删除某个离职员工的账号后发现/data下有大量文件属主显示为一串 UID 数字。排查命令find /data -nouser -o -nogroup 2/dev/null输出结果会列出所有找不到属主或属组的文件。处理方式有三种第一种如果确认这些文件已经无用直接清理find /data -nouser -o -nogroup -delete 2/dev/null第二种如果文件还有价值希望转移到某个现有用户手中find /data -nouser -exec chown dev01:devteam {} \;第三种如果历史遗留太多需要先盘点再决定建议先导出列表归档再逐个处理。最怕的就是不管不顾直接删掉整个/data目录连根拔起容易误删有保留价值的备份。这个问题的根源在于用户删除后系统不会主动巡视文件系统寻找该用户遗留的文件。所以在删除用户前我习惯先执行一遍find / -user 用户名摸底把所有归属文件列出来再决定这些文件是转交、归档还是销毁。5.3 UID 冲突一个新用户继承了旧人的文件反向场景比上一个更隐蔽删掉用户 A 之后系统新建用户 B 时自动分配了一个曾经被别人用过的 UID于是 B 用户直接继承了 A 留下的所有文件权限。Linux 内核不区分“这个 UID 以前属于谁”它只看数字。因此一个重要的实操原则是在定期清理用户前把旧用户的 UID 号记录下来后续新建用户时要么刻意避开要么在创建后立即检查属主归属。批量创建用户时建议手动指定起始 UIDuseradd -u 2001 dev01 useradd -u 2002 dev02这样可以把用户和 UID 的对应关系牢牢掌握在自己手里避免系统自动分配造成数字漂移。个人经验是高于 6000 的 UID 段常年处于“合规检查”范畴很多企业内部规范甚至会限制 UID 不能超过某个阈值提前规划数值段位能减少很多合规层面的麻烦。5.4 组权限不生效明明用户已经在组里这个问题的经典程度不亚于“重启解决 80% 问题”。用户说我已经被加进 devteam 组了但访问/data/project还是报权限不足。第一反应不是改目录权限而是让用户重新登录一次。附加组的变更不会动态应用到当前已登录的会话进程。用户必须注销重新登录或者如果只是不想退出可以执行newgrp devteamnewgrp命令会启动一个指定主组的新 shell临时切换会话身份。但这个办法只影响当前终端其他已登录会话依然保留旧组信息。如果重新登录后仍然不行执行id确认实际生效的 GID 列表id dev01输出中会列出uid、gid、groups三部分。如果 groups 列表里没有 devteam说明组加晚了当前会话还在用旧身份如果 groups 里能看到 devteam那就需要检查目录权限本身用namei -l /data/project逐级排查每一层目录的权限设置。这个命令会把路径上所有层级目录的权限完整列出来方便定位是哪一级卡住了。很多权限问题其实不是最终的目录/文件本身权限不对而是中间某一层目录缺少执行权限导致路径根本无法穿透。5.5 账号到期与密码过期混淆外部协作者反馈“账号过期了”但查下来发现是密码过期不是账号失效。密码过期意味着用户可以正常登录但登录过程中系统强制要求修改密码账号失效则直接拒绝登录即使输入正确的密码也没有用。两种现象区别明显密码过期输入正确密码后系统提示需要设置新密码。账号失效输入正确密码后直接提示账号已失效。排查工具还是那两个chage -l ext01 chage -E -1 ext01-E -1用来清除账号失效日期适用于“上个月该账号过期了但这个月续签了所以需要恢复”的场景。在管理外部协作者时我已习惯于把每个到期账号的失效日期统一维护在一张清单里每次续签后随手更新清单比靠脑子记忆靠谱得多。5.6 无法删除用户进程占用与主组残留执行userdel时提示无法删除用户的邮件池或家目录常见原因是该用户仍有进程在运行。排查pgrep -u dev01如果有进程输出先评估这些进程是否可以被终止。确认无误后pkill -u dev01 userdel -r dev01还有一种情况是主组残留。若用户的主组被设置成其他组的 GID并且该组下还有其他成员userdel可能不会提示错误但逻辑上需要你关注是否要手动清理空组或者把一个组的成员全部移出后再删除。这个细节属于低频率但高干扰的问题遇到了就需要耐心检查ps -ef的输出别急着强制-f删除。6. 将用户管理整合进日常运维习惯配置一次用户和组不难难的是后续长期维护不出乱子。这里分享几个我已经稳定使用多年的习惯希望你能少走弯路。第一把所有用户和组变更操作纳入变更记录。无论是新建账号、修改附加组还是删除用户都在内网记录里留痕。一次操作的代价很小但当你三个月后回看这个账号为什么存在时这条记录能帮你节省一整天的排查时间。第二定期检查孤儿文件和数字属主。我一般每个月跑一次find / -xdev -nouser -o -nogroup 2/dev/null把结果和自己的变更记录比对能及时发现是谁删除了账号但没清理数据或者是谁迁移数据时搞乱了属主。第三谨慎使用递归 chown 和 chmod。chown -R dev01:devteam /data/project是很直观的一条命令但如果你在/data级别误操作整个目录树的所有权都会被牵连。我的习惯是先备份当前属主关系再动手修改find /data/project -printf %u:%g %p\n /tmp/ownership_backup.txt第四给用户设置合理的 shell 与资源限制。普通开发人员完全不需要/sbin/nologin但后台服务账号必须用 nologin交互用户建议叠加资源限制防止某个失控脚本拖垮整机。在/etc/security/limits.conf里写明白每个组的进程数限制和 CPU 时间限制多用户环境里非常有价值。回到开头那句话用户与组管理看似基础却是所有权限体系的地基。地基打得稳后面的权限审计、等保合规、故障追责都会轻松很多地基上一旦留下烂账迟早要花更大的代价去填坑。如果你刚接触这块别急着追求复杂方案先把用户、组、权限三层关系理清楚用id、namei、find这三个命令玩熟你就能比大多数只会用管理员账号的人强出一大截。