首页 / 资讯中心 / 文章详情

Linux用户与用户组管理实战:从配置文件到命令详解

Linux用户与用户组管理实战:从配置文件到命令详解 ★ FEATURED ARTICLE
到第3关了前面基础命令、文件权限折腾下来你手里已经有一把能跟系统对话的钥匙。这一关的内容看起来很简单——不就是加个用户、分个组嘛但真正在Linux上做用户/用户组编辑知识点密度比你想的高得多而且在服务器上是动一发牵全身的操作。我见过不少新手在这上面翻车useradd少挂一个参数新用户没家目录usermod漏了-a把用户原本所在的附加组全覆盖掉账户直接失联。这些问题可不像删个文件那样能轻松恢复尤其是在人多、权限复杂的服务器上。所以这一关的核心就是Linux用户管理最终目标是你随手写的每一条用户、用户组相关命令都清清楚楚知道它动了哪几个文件、改了几个字段、会不会误伤到正在跑的进程。1. 用户管理的底层机制先看懂三个配置文件1.1 看穿 /etc/passwd用户的“登记册”好多初学者有个错觉觉得Linux用户是存在某个神秘的数据库里。不是。Linux用户的静态信息本质上就是几个普通的文本文件。最核心的是/etc/passwd相当于整台机器所有用户的登记册。你cat一下每行是一条用户记录每条被冒号切成7个字段顺序固定少一个字段或者多一个字段用户解析就会出问题。字段依次是用户名、密码占位符、UID、GID、注释通常写全名或职务、家目录路径、默认shell。这里有两个容易忽略的点。第一密码占位符绝大多数情况下是个x它只表示“密码被挪到shadow文件里了”并不承载真正的密码。第二UID不是随便排的系统里有一道默认的分界线0给root1到999是系统账户不同发行版范围略有差异1000以上才是普通用户。这条分界线的意义在于系统服务也要用独立账户来跑不能让他们用root也不能占普通用户的段位。所以你在生产环境看到UID是1010这种数字基本可以判断这是个后加的真人账户。有人会问这个文件全系统可读密码为什么写在passwd第二列也没事因为设计上早就把密码挪走了这就是/etc/shadow存在的理由。至于手动改这个文件我的建议是学习阶段你打开看看没问题生产环境别用vim直接改要改就通过vipw。vipw会对/etc/passwd加锁防止你改的时候有人同时在用useradd两个写入撞车导致文件错乱。这个错乱一旦发生轻则某个用户解析失败重则所有用户都登录不了只能进救援模式收拾残局。别给自己找事。1.2 /etc/shadow密码、锁定、有效期都在这里/etc/shadow是真正的核心机密库只有root可读。里面每行也是一条用户记录用冒号分成9个字段常用的是前几个用户名、加密后的密码、最后一次修改密码的日期、密码最小使用天数、最大使用天数、过期前警告天数、停止使用宽限天数、账号过期日期、保留字段。解释三个关键点。第一日期字段都是从1970年1月1日起算的天数所以看到字段里是个四位数甚至五位数不要奇怪这是Linux系统时间的经典算法。第二加密密码字段里常见的是$6$开头表示SHA-512散列算法如果这个字段是空的说明用户没有密码这种账户超级危险属于高危隐患。如果前面有个!或者只有一个!说明账户密码被锁定用户无法通过密码正常登录。第三shadow文件权限是600属主root普通用户连读都不会有这才是它存在的意义。为什么非要把密码单独拆到shadow因为早期Linux的密码哈希就放在passwd第二列而passwd所有用户都有读权限于是整台机器每个用户都能把密码哈希拖走做离线破解哪怕用的是当时算力下相对费劲的加密算法一台普通电脑跑一晚上也能跑出不少弱口令。后来的方案就是权限收紧把密码挪进root-only的shadow普通用户根本读不到破解门槛一下就立起来了。这个迁移的工程设计思路放到今天仍然不过时敏感信息永远要和大众可读的信息分离。1.3 /etc/group 与 /etc/gshadow组的两张面孔组的信息分两个文件。主文件是/etc/group每行4个字段组名、组密码占位符、组GID、附加成员列表。注意主组的成员名单不在这里体现用户在passwd里的GID字段才指认他的主组。这个区别我当年搞混过后来踩了坑才记住组文件里列出来的是“以这个组为附加组”的用户。主组和附加组是什么关系一个用户只能有一个主组但可以有多个附加组。比如用户A的主组是dev附加组可以同时是ops、docker。实际权限判定时用户同时拥有主组和所有附加组的权限只要某个组对文件有读取权他就能读。所以把用户加进哪个组本质上就是在给他叠加权限集合组越多权限越杂安全边界就越糊。这也是为什么建议建组要有规划别图省事全丢进同一个组。/etc/gshadow则是在有组密码需求的场景下才凸显价值它存组密码和组管理员列表。日常小环境用得很少但你的组要开放给非成员临时加入、或者想指定某个人来代管组成员时就得靠它。学的时候你至少要知道组密码这个概念存在真遇到需求查一下就能接上。整个用户管理的静态数据就落在这四个文件里。文件越稳定越好手动改要克制接下来看命令怎么围绕这些文件做增删改查。2. 用户的增删改查从useradd到userdel2.1 useradd你创建的每一个用户都要“合身”useradd是创建用户的主命令但新手最常见的坑就是以为useradd这个用户名就够了结果创建出来的用户既没有家目录shell还是sh登录体验一言难尽。原因在于useradd的大部分行为依赖默认配置默认配置存放在/etc/default/useradd和/etc/login.defs里。不同发行版的默认值不一样有的默认创建家目录有的默认不创建所以跨环境操作时特别容易迷失。一条比较稳妥的创建命令是这样useradd -m -s /bin/bash -d /home/dev_a -g developers -G ops,docker -c 开发人员A dev_a逐个解释。-m表示创建家目录并把/etc/skel下的骨架文件复制进去-s指定登录shell为/bin/bash普通用户别给nologin否则他登不进来-d指定家目录路径通常和用户名保持一致-g指定主组注意这个组必须已经存在不然命令直接报错-G指定附加组可以逗号分隔多个-c写用户注释一般放姓名或岗位。创建完后建议马上验证一下id dev_a ls -ld /home/dev_aid输出的第一行会显示uid、gid以及groups一眼就能确认主组和附加组是否配置正确。家目录权限通常是700属主是dev_a注意如果这里出现权限不对后面用户登录后连自己家目录都进不去会引发一系列莫名其妙的问题。这个细节我在第一次批量建用户时踩过后来每次创建完都会顺手ls -ld确认目录状态。2.2 usermod改用户属性是一场精细手术用户创建之后要改东西用usermod。这命令看着和useradd参数长得差不多但有几个差异很容易让人翻车。最经典的就是-G和-aG的问题。-G是直接覆盖用户当前的附加组列表。比如一个用户原本在ops组你执行usermod -G docker user他的附加组会从ops变成dockerops权限直接没了。而-aG是追加在原有附加组基础上再加一个这才是大多数人想要的效果。运维里流传的那句“加组一定要带-a不然会把人搞丢”指的就是这个。我亲眼见过有人给用户加docker组时忘了-a导致用户从sudo组掉出去权限瞬间丢失服务部署到一半卡死。所以请把usermod -aG当成肌肉记忆。改用户名和家目录也是个高频场景。正确姿势是把改名和移动家目录放在一条命令里usermod -l dev_a_new -md /home/dev_a_new dev_a-l修改用户名-d修改家目录字段-m把旧家目录里的内容整体搬移到新路径。如果不加-m家目录路径在配置里变了但旧目录还留在原地用户登录后可能会在一个空壳目录里抓瞎。锁定和解锁账户也有对应参数。usermod -L会在shadow密码字段前面加个!usermod -U去掉!恢复。用这个场景很广泛比如员工离职、账户被爆破、发现异常登录都可以先锁住再说。锁用户和删用户是两码事锁定后账户还在随时能解比直接删除稳妥得多。还有个容易忽略的细节修改用户的UID或GID后这个用户家目录里所有文件的属主数值不会自动跟着变。如果你usermod -u改了UID记得要chown -R新UID:新GID /home/用户名否则用户会看到自己的文件全变成“nobody”所有各种权限报错扑面而来。这个坑在把某用户的UID从普通段调整到系统段时尤其常见。2.3 userdel删用户最容易“留尾巴”删除用户的命令是userdel但直接执行userdel用户名只会删除passwd、shadow、group等文件里的记录家目录和邮件池统统留在磁盘上。这里有两个层面的麻烦。第一是磁盘垃圾用户走了家目录可能塞了几十G数据长年累月不清理服务器硬盘悄无声息就满了。第二是安全隐患一个已删除用户的目录还在如果里面存了敏感文件而目录权限设置不当其他用户可能读得到。所以删除时一般用-ruserdel -r dev_a-r会把家目录和邮件池一并清理。但事情没那么简单如果该用户当前有进程在跑系统会提示“user xxx is currently used by process xxx”这时候删不掉。正常流程是先用命令确认没有他残留的进程确认无误后再删pgrep -u dev_a userdel -r dev_a我习惯在删除一个账户之前先passwd -l或者usermod -L把它锁住等确认没有关联任务了再执行userdel -r。锁住和删除之间留一段观察期能避免很多“删早了被业务方找回来”的尴尬。另外注意删除用户并不会自动删除他作为主组的那个组。如果那个组已经没有其他用户会变成无主组残留下来需要手动groupdel清理。删人容易收尾难说的就是这个。3. 用户组group系列命令的完整闭环3.1 groupadd建组之前先想好GID建组命令是groupadd简单场景下一条命令就够了groupadd developers系统会自动分配一个大于1000的GID。但如果你对GID有规划比如公司内部按部门划分段位或者要和某台老服务器保持GID一致就要显式指定groupadd -g 3001 developers-g的作用是手动指定GID避免和其他组冲突。还有两个小参数经常在脚本里很有用-r创建系统组GID落在系统范围-f在组已经存在时直接静默退出不报错。写批量脚本时-f能让你不用先判断组是否已经存在省去一大堆if逻辑。建组之前要想清楚的问题是这个组到底承担什么权限边界。比如developers组给开发人员用ops组给运维用数据分析组给BI同事用。组和组之间最好不要出现“一个组里既有开发又有财务又有运维”的情况否则你后面做目录权限隔离时会发现谁都能访问所有东西组的存在等于没有。组权限的设计思路就是让每个人只拿到完成工作所需的最小权限集合而不是给一个大而全的“万能组”。3.2 groupmod与groupdel改名、改ID的边界条件组建好了后续要改名或改GID用groupmodgroupmod -n development developers groupmod -g 3002 development第一条把developers改名为development第二条把GID从3001改成3002。看起来简单但影响范围不小。特别是改GID之后之前所有以该组为属主的文件组归属数值不会自动更新需要手动批量调整。所以在生产环境里我通常建议“宁可重新建一个组也不要轻易改老组的GID”除非你有完整的文件扫描和chown计划。删除组用groupdel。这里有个明确限制如果某一个用户把这个组当成了主组groupdel会直接拒绝执行。系统会提示该组是哪个用户的主组你必须先把用户的主组改掉或者先删掉那个用户才能继续删除组。如果你只是想清理一个已经没有成员的空组直接groupdel就行。3.3 让组真正发挥作用目录权限配合组建好、人也加进去如果不同步调整目录权限这个组等于白建。最常见的做法是把共享目录的属组改成目标组并设置组权限chown :developers /data/project chmod 2770 /data/project命令后面的数字有点讲究2是setgid位它让目录里新建的文件自动继承目录的属组而不归创建者自己的主组这是多人协作目录最关键的配置770表示属主和属组都有读写执行权限其他人完全进不来。配合setgid位开发团队的成员不管谁来建文件文件属组都是developers大家互相能读写外部人员一律挡在外面。这套“用户组目录权限”的组合拳就是Linux协作目录的经典套路。如果你需要临时把一个用户加入组、踢出组除了usermod还可以用gpasswdgpasswd -a dev_a developers gpasswd -d dev_a developers-a是添加成员-d是移除成员。gpasswd还支持给组设置组密码直接执行gpasswd组名以及用-A指定组管理员。组密码这个功能日常环境用得少但在某些需要“非本组成员临时加入共享组”的场景里很实用。建议至少了解这些能力的存在真到用的时候查文档不慌。4. 密码策略与账户安全passwd、chage与login.defs4.1 passwd不只是“改密码”三个字创建用户后的第一件事是设置密码命令就是passwdpasswd dev_a交互式输入两次新密码就完事。如果你需要批量设置密码也可以把密码通过管道喂给命令echo Str0ng#Pass123 | passwd --stdin dev_a--stdin让passwd从标准输入读密码这在初始化脚本里是常见写法。但我要提醒一句这个写法会使密码出现在命令行历史里生产环境慎用。更稳妥的做法是用chpasswd同样支持管道输入且不会在ps输出中直接暴露明文echo dev_a:Str0ng#Pass123 | chpasswdpasswd还有其他实用参数-l锁定密码-u解锁-d删除密码会让用户变成无密码状态-S查看当前密码状态。其中-l和usermod -L效果类似都是在shadow的哈希前面加!普通人登录时密码永远验证不通过。你要排查一个用户能否正常登录先passwd -S看一眼状态比反复猜测原因高效得多。密码强度方面我自己对待用户密码的态度是至少12位包含大小写、数字和符号不要用生日、公司名、键盘连续字符。服务器上被爆破的账户绝大多数都是因为密码太弱这个锅不该系统背。4.2 chage让账户“到期自动失效”chage是管理密码时效和账户有效期的工具很多人平时用不到一旦要管临时账户或合规审计它就是核心命令。最常用的是-M、-W、-E三个参数chage -M 90 -W 14 dev_a chage -E 2026-12-31 temp_b-M 90表示密码最多使用90天必须更换-W 14表示密码过期前14天开始警告-E指定账户到期日期到了这个日期账户直接失效无法登录。对临时外包、短期合作方账户到期日期几乎是必须设置的不然项目结束、人员离开账号还在系统里挂着是一个不小的安全死角。还有一个令新手惊讶的用法chage -d 0 dev_a。这个命令把“最后一次修改密码日期”设为0强制用户在下次登录时必须先修改密码才能继续操作。当你希望管理员初始化账号后第一次登录由用户自己改密码时这一招比任何花哨操作都实用。配合chage -l查看之后你能看到完整的密码时效信息确认策略是否生效。4.3 默认策略藏在login.defs里/etc/login.defs是用户创建时的默认策略来源它里面定义了新用户的UID范围、密码最大天数、密码最小天数、警告天数、是否默认创建家目录等一系列参数。比如PASS_MAX_DAYS 90 PASS_MIN_DAYS 0 PASS_WARN_AGE 14 UID_MIN 1000 UID_MAX 60000这里的特点是login.defs只影响之后新建的用户已经存在的用户不会自动套用这些新策略。所以你在生产环境想推行“所有用户密码90天必须改一次”光改login.defs还不够已有的账号必须再用chage -M 90逐一修正或者写个循环脚本批量处理。另外要注意不同发行版对login.defs的默认值可能不同RHEL系和Debian系在密码策略细节上都有差异。如果公司的安全规范要求更严格的密码策略在每台新服务器上线时就要把login.defs一并调整好而不是等出了审计问题再补救。这种基础配置最怕“平时不管检查时突击”。5. 实操场景从需求到落地的一整套用户交接5.1 需求先想清楚纸上谈兵不如实战一趟。假设某个项目组来了位新开发人员A职责是写后端代码需要登录服务器、需要访问团队共享的/data/project目录还应该能执行sudo里的运维命令具体能不能sudo看公司规范这里用“ops”组举例。另外还有一位临时外包人员B只参与两周的数据整理给一个临时期限的账号。先规划再动手规划项包括用户名、主组、附加组、家目录、shell、密码时效、账户到期日期。规划结果可以写成一张表项目开发人员A临时人员B用户名dev_atemp_b主组developerstempgroup附加组ops无家目录/home/dev_a/home/temp_bshell/bin/bash/bin/bash密码时效90天90天账户到期不设两周后这个规划的过程本质上是把需求翻译成系统配置。很多新手的问题在于拿到需求直接敲命令结果临时账号没设到期日、正式账号漏了附加组事后又是一堆补丁操作。规划这一步能省掉后面80%的返工。5.2 落地操作全记录按规划执行先建组再建用户因为useradd指定主组时主组必须已经存在groupadd developers groupadd tempgroup useradd -m -s /bin/bash -d /home/dev_a -g developers -G ops -c 开发人员A dev_a useradd -m -s /bin/bash -d /home/temp_b -g tempgroup -c 临时人员B temp_b echo dev_a:InitPass123 | chpasswd echo temp_b:InitPass456 | chpasswd chage -M 90 -W 14 dev_a chage -M 90 -W 14 temp_b chage -E 2026-07-31 temp_b给dev_a配置共享目录权限并设置setgid位。注意顺序先建目录、再改属组、最后调权限mkdir -p /data/project chown :developers /data/project chmod 2770 /data/project最后让dev_a加入共享组的常规通道。如果他在使用过程中需要临时访问其他组资源再按需追加gpasswd -a dev_a developers这里我没用usermod -aG因为创建用户时已经把dev_a的附加组设置成ops了现在只是确认他同时属于developers组。实际场景里你既可以在创建时写-G developers也可以在创建后gpasswd -a效果相同按自己的习惯来。5.3 验证与回滚命令执行完不算结束必须逐项验证。验证项目至少包含用户信息、组信息、家目录权限、共享目录权限、密码状态、到期日期。id dev_a getent passwd dev_a getent group developers ls -ld /home/dev_a ls -ld /data/project passwd -S dev_a chage -l temp_b我每次都会把这几行挨个跑一遍确认输出和预期一致再交付。id确认主组和附加组getent确认配置文件里真的写进去了ls -ld确认目录属组和权限passwd -S确认非锁定状态chage -l确认到期日。任何一项输出和规划不符当下就修不要留到业务方反馈。如果发现创建错了回滚操作也很明确删除用户并清理家目录删除组把目录权限还原。比如误建了两个用户执行userdel -r dev_a userdel -r temp_b groupdel developers groupdel tempgroup chmod 0755 /data/project chown root:root /data/project回滚之后务必再验证一次确认没有残留用户和组。如果你回滚完只检查了用户列表忘了查组和目录权限很容易留下半残状态。6. 常见问题与排查技巧实录6.1 症状与原因速查表症状常见原因处理方式新用户登录后没有家目录useradd没加-m或家目录权限不对usermod -m -d /home/用户名 用户名加了附加组后原来的sudo权限没了忘了-a直接-G覆盖了原有附加组usermod -aG sudo 用户名 重新加回userdel提示用户进程占用用户还有进程在跑pgrep -u 用户名确认kill进程后再删groupdel提示组是某用户主组该组还被用户当作主组先修改该用户主组或先删除用户改UID后文件属主变nobody文件属主数字没同步修改chown -R 新UID:新GID /home/用户名用户到期后仍能登录只设了密码有效期没设账户到期日期chage -E 2026-12-31 用户名 补设临时账户删除后组残留userdel不会自动删主组groupdel 组名 手动清理这张表我写的时候特意覆盖了前几章讲到的每一个高频坑。你也可以把它截图或者存成笔记碰到同样症状先对照排查能省很多时间。6.2 那些文档不写、但生产环境真的很重要的“坑”最后分享几个只能靠实际经验攒下来的习惯。第一不要在服务器上直接用echo加管道设置密码就完事至少要把命令放进脚本文件并在文件权限上做限制或者用chpasswd配合临时文件用完立即删除。因为密码一旦出现在shell历史或者ps输出里就等于半公开了。这个问题我在早期管理测试服务器时吃过亏后来所有批量初始化密码都改成脚本处理历史记录里再也看不到明文。第二批量创建用户时不要简单用shell循环叠加useradd就完事。用户多的时候建议把账号信息整理成格式化的文本用newusers一次性导入再配合chpasswd批量设密码。newusers虽然看起来不如循环直观但它能保证一批账户的UID、GID、家目录、shell一次性写进配置文件出错概率低很多。尤其是在管理上百台服务器的场景里这种批量工具的价值远大于手写循环。第三修改用户或组之前先把/etc/passwd、/etc/shadow、/etc/group、/etc/gshadow这四件套备份一份。备份方式很简单cp /etc/passwd /etc/passwd.bak cp /etc/shadow /etc/shadow.bak cp /etc/group /etc/group.bak cp /etc/gshadow /etc/gshadow.bak别看这个操作土关键时刻能救命。配置改乱了直接替换回去就能恢复不用进救援模式折腾。我在生产环境做任何涉及用户和组的变更前都先备份几分钟的事换来的是一晚上的安稳觉。第四关于sudo权限的坑。不同发行版对管理员组命名不一样有的叫wheel有的叫sudo如果要把用户加进管理员组先确认当前系统的组名再操作。盲目把用户加进一个不存在的组命令会报错用户反而拿不到任何管理员权限。用getent group sudo getent group wheel提前看一眼比凭记忆硬写靠谱。最后再补一个很小但很实用的技巧排查用户登录异常时别只盯着passwd和shadow。有时候问题出在/etc/nsswitch.conf或者远程登录服务的配置上比如某个用户能su但不能ssh很可能是远程登录服务把允许登录的用户列表限制住了。遇到这种情况先查别急着改passwd把范围缩小到最可能的原因比反复折腾用户配置高效得多。这一关的内容就到这里剩下的是在你自己的服务器上多建几个用户、多删几个组亲手踩一遍坑才算真正过关。
阅读完成 · 觉得有帮助?
咨询建站