
1. 先搞清楚用户管理到底在管什么很多初学者拿到一台Linux服务器第一个想法就是赶紧跑几条命令把用户建出来但真正遇到生产环境的问题时往往一脸懵。归根结底是因为没搞明白用户管理本质上在管什么——它管的不只是“谁能登录”还包括“登录之后能干什么”“每个进程到底以谁的身份在跑”“文件归属谁”这三个层次。Linux里的用户不是给人看的它是内核做权限判断的基本单位。你敲下的每一条命令最终都会对应到一个UID用户ID和一组GID组ID。内核看到的是数字不是用户名。所以用户管理的核心就是维护“用户名 ↔ UID/GID ↔ 文件权限 ↔ 进程身份”这条链路。任何一环对不上轻则权限报错重则服务起不来、文件读不了。这篇文章适合刚入门Linux但已经会基本操作的同学也适合那些在服务器上建过用户、但只会useradd加passwd、遇到权限问题就抓瞎的运维新手。我会把用户管理的全部常用命令串成一个清晰的知识体系并且把我在真实服务器上踩过的坑一并写出来。1.1 用户与进程、文件的权限关系先打一个生活化的比方。Linux系统像一栋办公楼用户是进出大楼的人UID就是工牌编号文件是办公室里的文件柜。每个文件柜上都贴着“谁可以看、谁可以改、谁碰都不能碰”的标签这就是文件的属主、属组和其他人权限。当你登录系统执行某个程序这个程序就自动变成你的“代理人”它拿着你的工牌去访问文件。这就是为什么你在某个目录下创建的文件默认属主就是你自己别人删不掉。进程权限的粒度就卡在这个“工牌身份”上完全由用户和用户组决定。这也解释了一个常见现象为什么用某个服务账号比如运行Web服务的用户跑的程序只能写它自己的目录写不了别的应用目录。这不是程序写得有问题而是你给它的身份范围就这么大。理解这一点后你就知道用户管理的真正意义——它不是简单的“加人减人”而是为系统里的每一个进程和每一份数据划定边界。1.2 用户信息存在哪三个关键文件看用户管理一定要先知道数据存在哪。Linux把用户信息分散在三个文件里所有命令最终都在操作它们文件作用主要内容/etc/passwd用户账户基础信息用户名、UID、GID、家目录、登录Shell/etc/shadow密码与有效期信息加密密码、密码修改时间、过期策略/etc/group用户组信息组名、GID、组成员列表很多人第一次看到/etc/passwd里有一串x以为是密码其实那只是占位符真正的密码哈希在/etc/shadow里只有root能读。这个设计是有讲究的/etc/passwd需要被很多命令读取比如ls要显示文件属主名如果密码也放在这里普通用户就能拿到哈希去做暴力破解。拆开之后影子文件权限收紧安全系数大幅提升。/etc/group里有个容易忽略的字段——组的成员列表。注意这里只记录“把某个组作为附加组”的用户而用户在/etc/passwd里那个GID对应的组叫“主组”也叫初始组不会重复出现在/etc/group的成员列表里。这个区别在管理用户权限时非常重要后面讲usermod的时候会具体展开。2. 日常使用频率最高的用户增删改查命令用户管理的命令并没有想象中那么多核心就四个useradd、usermod、userdel、passwd。但每一条命令的参数都很丰富而且在不同发行版上默认行为还不一样必须逐个讲透。2.1 创建用户useradd 的参数取舍先看一个最常见的创建命令useradd -m -s /bin/bash -G wheel testuser参数说明如下-m创建家目录。不写这个参数时很多发行版不会自动建家目录后面登录可能连home都没有。-s指定登录Shell。给普通业务用户一般用/bin/bash给服务账号用/sbin/nologin禁止交互登录。-G指定附加组。注意是小写的G把用户加进附加组大写的-g是设置主组两者别搞混。创建一个用户最少要带-m -s否则你会踩到“用户创建成功但登录后没有家目录”的坑。那默认参数呢不同发行版差异很大。比如在某些发行版上useradd默认就带-m在另一些上则不带。判断当前系统默认值的方法是看/etc/default/useradd这个文件还有/etc/login.defs里的配置项。如果你管着几十台混合发行版的服务器建议统一写成完整参数别依赖默认行为。还有一点UID的分配。系统会自动取当前最大UID加1生产环境里如果想控制UID范围比如普通用户从1000开始同样是在/etc/login.defs里配置。2.2 修改用户usermod 的实用场景usermod是用户管理的“瑞士军刀”。几个高频用法# 修改用户的主组 usermod -g devgroup testuser # 把用户加入附加组保留原有附加组 usermod -aG docker testuser # 修改家目录路径 usermod -d /data/home/testuser -m testuser # 锁定/解锁账号 usermod -L testuser usermod -U testuser这里最需要强调的是-aG里的那个-a。我看到太多新手直接usermod -G docker testuser结果这个用户之前所在的所有附加组全部被清空只剩docker。因为-G默认是“覆盖式”设置不加-a就是重置。生产环境上一旦把用户的附加组覆盖掉他可能立刻失去sudo权限、失去访问某些共享目录的资格问题相当隐蔽。-d和-m一起用时是把家目录从旧路径搬到新路径。搬完记得检查目录权限归属如果是root搬的家目录属主可能变成root需要再chown回去。-L和-U是锁定和解锁密码。注意锁定的是密码认证如果用户配了SSH公钥登录他依然可以免密登录这点在高安全环境里要格外小心。2.3 删除用户你真的会删吗删除用户我用得比较少但每次用都特别谨慎。命令是userdel testuser如果不带任何参数这个用户的家目录和邮件池mail spool会残留下来。想要一并清干净用userdel -r testuser-r会连家目录和邮件目录一起删。但这个“干净”同时也是风险——如果这个用户的家目录下有其他服务正在用的数据比如网站上传目录userdel -r会把整棵目录树全部删掉而且不会进回收站。所以我自己的习惯是先检查用户是否还有在跑的进程、是否有文件归他所有确认没问题再删。检查命令很简单ps -u testuser find / -user testuser 2/dev/null把查出来的文件先chown给其他用户或直接归档备份再执行userdel。生产环境上删用户从来不是一条命令的事前面几步检查往往比删除本身更花时间。2.4 密码与认证passwd 和 chage密码是用户认证的第一道门槛命令不多但规则很重要# 修改自己密码 passwd # 修改指定用户密码root才有权限 passwd testuser # 删除密码变成无密码登录一般不推荐 passwd -d testuser这里要留意chage这个命令中文经常叫“密码过期管理”。如果你希望某个账号三个月强制改一次密码用它最方便chage -M 90 testuser chage -W 7 testuser-M设置最长有效期90天-W设置到期前7天开始警告。如果想查看用户的密码过期信息chage -l testuser输出里能看到最近修改日期、密码过期时间、账号过期时间等。这条命令在安全审计场景下很有价值——能快速找出哪些账号快过期了、哪些账号密码已经失效但还没被禁用。顺便提醒一句passwd -S testuser可以看密码状态是否锁定、是否设置时间排查“用户登录不上”的时候非常有用。3. 用户组管理和批量权限分配用户组是权限的“打包机制”。如果把用户比作人组就是部门文件系统通过组来批量授权省去一个用户一个用户地设置权限的麻烦。这一节讲组管理命令和批量场景。3.1 用户组的创建、修改、删除组命令和用户命令几乎是镜像关系# 创建组 groupadd devteam # 指定GID创建组 groupadd -g 1500 devteam # 修改组名 groupmod -n devteam2 devteam # 删除组 groupdel devteam删除组时有个坑如果某个用户的主组primary group正好是这个组groupdel会直接报错提示这个组不能删除因为它是某个用户的主组。你需要先把这个用户的主组改掉才能删除组。说白了Linux不允许一个用户的“身份标识”悬空。groupmod -n改名时要注意是否有脚本或配置文件里写死了旧组名。组改名后文件系统里那些以GID记录的属组关系会保留文件存的是GID不是组名但所有引用组名的配置就需要同步改否则就会出现“文件显示属组是旧名字但/etc/group里已经没有这个组”的尴尬状态。3.2 把用户塞进组gpasswd 和 usermod往组里加人最常用的两条路# 把一个用户加入组 gpasswd -a testuser devteam # 把用户从组移除 gpasswd -d testuser devteam # 或者用 usermod 追加方式上一节已经讲过 usermod -aG devteam testuser为什么有两套命令因为场景不同。如果你要一次性把多个用户加入某个组、或设置组管理员gpasswd更合适如果只是在某个用户身上追加权限usermod -aG更直观。gpasswd还有一个特殊用途设置组密码。组密码允许用户不必成为组成员也能通过newgrp命令临时切换身份。在生产环境里我其实不太推荐用组密码因为它等于在用户和组“是否属于”的判断上开了一个口子审计时容易出漏洞。如果确实需要临时权限用sudo规则更可控。3.3 批量创建用户的思路与脚本要点服务器数量多了以后手工一条条useradd显然不现实。批量创建用户的标准做法是准备一个格式化的用户列表用循环脚本跑#!/bin/bash while IFS: read -r username fullname group do if ! id $username /dev/null; then useradd -m -s /bin/bash -G $group -c $fullname $username echo 用户 $username 创建成功 else echo 用户 $username 已存在跳过 fi done users.txtusers.txt每行格式写成用户名:中文姓名:附加组一目了然。脚本里加一个id判断防止重复创建报错。密码部分我一般不写在创建脚本里而是创建后单独跑一遍chpasswd批量导入初始密码再强制用户首次登录改密码echo testuser:Temp123 | chpasswd chage -d 0 testuserchage -d 0的意思是强制用户在第一次登录时修改密码。批量场景下这就避免了自己拿着明文密码分发时的安全隐患。4. 查看用户与登录状态从账号信息里发现异常查询命令是运维排查的起点。很多问题不是“用户建不出来”而是“用户感觉不对劲”——时区不对、环境变量不对、目录权限不对。这时候你需要快速看清楚账号的一切。4.1 id、who、w、last 等命令怎么看先看一条最基础但最实用的id testuser输出示例uid1001(testuser) gid1001(testuser) groups1001(testuser),10(wheel)这里能看到UID、主GID和附加组列表。查询时建议重点看groups那一列判断用户的权限边界。比如groups里没有wheel那他就没有切root的资格如果你的系统里sudo规则是基于组成员判断的这里就是第一排查点。再看登录相关的命令# 当前登录了哪些用户 who # 更详细的登录信息包含负载、终端、登录时间 w # 历史登录记录 last # 最近几次登录失败的记录 lastblast是排查“这台机器还有谁会登录”的好工具它读取/var/log/wtmplastb读取/var/log/btmp记录认证失败的尝试这在高风险场景里很重要——如果某个IP频繁出现认证失败记录说明可能有人在爆破你的账号。4.2 从账户信息判断账号安全性我每次安全巡检都会做三件事一是把UID为0的账号全部列出来因为UID为0意味着超级用户权限理论上只能有root一个awk -F: $3 0 {print $1} /etc/passwd二是查空密码账号awk -F: ($2 || $2 !) {print $1} /etc/shadow三是查“有登录Shell但不是root”的账号到底有多少。很多服务账号用的是/sbin/nologin如果发现某个服务账号配了/bin/bash就要警惕是不是有人为了调试方便改的在正式环境里这是安全漏洞。这些检查不需要额外装工具几条awk就能跑适合记成脚本固化下来。5. 身份切换与提权su 与 sudo 的正确姿势用户管理绕不开“提权”。日常操作里绝大多数管理员用root登录后直接操作这在单机环境问题不大但一旦涉及到多人协作、操作审计、最小权限原则就必须把su和sudo用明白。5.1 su 的用法和踩过的坑# 切换到testuser但不加载其环境变量 su testuser # 切换到testuser并加载完整环境变量 su - testuser # 切到root su -最大区别就在那个横杠-。su testuser只切换用户身份保留当前Shell的工作目录和环境变量su - testuser模拟该用户完整登录会执行目标用户家目录下的.bash_profile、.bashrc把PATH等环境变量全部切过去。很多新手用su切到某个用户后发现命令找不到比如java、docker第一个怀疑是安装出了问题其实只是没加载环境变量而已。所以我的建议是凡是用su切换身份一律习惯性加-除非你明确知道自己在干什么。su还有一个安全隐患要切换到root你得知道root的密码这就等于把root密码分发给所有有需要的人。人一多密码扩散面就大泄露风险成倍上升。所以生产环境里我几乎不用su切root改用sudo。5.2 sudo 规则配置/etc/sudoers 实战sudo的精髓是“不需要知道root密码也能以root身份执行指定命令并且留下日志”。配置文件在/etc/sudoers强烈建议不要直接改文件用visudo命令编辑它会帮你做语法检查避免写错导致sudo完全不可用。简单配置示例# 让wheel组成员能执行所有命令 %wheel ALL(ALL) ALL # 允许testuser无密码重启服务 testuser ALL(root) NOPASSWD: /usr/bin/systemctl restart nginx # 允许模板运维用户只能执行系统管理命令 %ops ALL(root) /usr/sbin/useradd, /usr/sbin/usermod, /usr/sbin/userdel注意三个核心概念主机列表、以谁身份、命令列表。ALL(ALL) ALL从左到右意思是“任何主机上、以任何用户身份、执行任何命令”。命令列表里写具体命令时尽量写全路径否则可能出现同名其他命令被利用的绕过场景。在实际操作中我还喜欢启用sudo的日志和默认拒绝策略Defaults logfile/var/log/sudo.log Defaults !visiblepw Defaults requirettyrequiretty要求sudo必须在真实终端下执行能在一定程度上防止某些脚本在非交互环境下滥用sudo。不过要小心如果你用自动化工具远程执行sudo这条配置会直接导致执行失败需要根据自己场景取舍。5.3 为什么我更推荐 sudo 而不是 su两段式总结一下。su的缺点是“一次获得全部权限、要共享root密码、行为难审计”。sudo则是“按命令授权、不需要共享密码、每条命令都有日志”。尤其在多人共管的服务器上发生误操作时sudo日志能精确告诉你谁在什么时间执行了哪条命令而su根本查不到。当然sudo不是完美的配置复杂规则多了容易出错。我见过有人把NOPASSWD配给ALL等于免密root还不如用su呢。所以sudo规则也要定期review尤其是那些“只加不减”的授权时间久了都是隐患。6. 文件归属调整chown 与 chgrp 的实战细节用户管理的一大部分工作最终会落到“让某个用户能访问某个目录/文件”上。除了权限位chmod还要管文件归谁所有这就是chown和chgrp。6.1 递归修改、引用式修改与安全区间# 修改属主 chown testuser /data/app # 同时修改属主和属组 chown testuser:devteam /data/app # 递归处理注意大小写R chown -R testuser:devteam /data/app # 只改属组 chgrp devteam /data/app使用chown -R要格外小心它是一把重剑。如果目录树里包含了软链接-R默认会跟随软链接进入目标目录这在某些场景下会意外改动不该动的位置。Linux还支持-h参数用来修改软链接本身而不是它指向的目标。另一个容易忽视的点如果只改属主不指定属组chown会把属组也改成该用户的主组。比如chown testuser /data/app最终属主和属组都变成了testuser。这符合多数预期但如果你只想改属主、保留原属组就要用chown testuser: /data/app这种带冒号不带组名的写法。6.2 用户家目录与文件归属的联动创建用户后家目录权限如果是错的后患无穷。正常家目录应该是属主为对应用户、权限为700或750。如果一台服务器之前由其他人操作可能存在家目录属主错乱的情况排查方法ls -ld /home/*看到家目录的属主是root或者其他用户就执行chown -R testuser:testuser /home/testuser chmod 700 /home/testuser注意家目录权限不建议设成777因为普通用户会在家目录里放自己的SSH私钥、脚本等敏感文件权限太开放等于门户大开。我自己一般给750这样同组的运维伙伴可以进入家目录协助排查但普通其他用户进不来。6.3 实际业务中“共享目录”的权限设计多人协作项目通常需要一个共享目录让一组人能读能写。推荐做法是建一个公共组把目录属组改成这个组再给目录设置setgid位groupadd shared usermod -aG shared testuser mkdir /data/shared chown root:shared /data/shared chmod 2770 /data/shared重点在于chmod 2770里的2也就是setgid位。它保证在这个目录下新建的文件其属组自动继承目录的属组shared而不是创建者自己的主组。这样整个小组的成员都能互相读写不需要反复chgrp。这是Linux共享目录的标准做法很多新手没设setgid结果A创建的文件B看不了问题就出在这。7. 场景实操从零搭建一个多用户服务器理论讲了这么多不如来一个完整场景把上面的命令串起来。假设我要在一台新服务器上做一次多用户环境初始化目标是给三个同事分别建账号其中两个属于开发组一个属于运维组运维组的人可以用sudo管理服务但不能改用户密码开发组的人只能进入项目目录禁止Shell之外的高危操作。7.1 场景需求与前置规划先把规划写出来用户dev_a、dev_b、ops_c组devteam开发组、opsteam运维组项目目录/srv/myapp访问权限devteam对目录有读写权限对项目日志有读权限sudo规则opsteam只允许执行systemctl管理服务不允许执行用户管理类命令在动手之前还要检查系统是否已有同名用户避免命令报错。这一步用id dev_a确认即可。7.2 具体操作步骤记录第一步建组和用户groupadd devteam groupadd opsteam useradd -m -s /bin/bash -G devteam -c Dev A dev_a useradd -m -s /bin/bash -G devteam -c Dev B dev_b useradd -m -s /bin/bash -G opsteam -c Ops C ops_c设置初始密码并强制首次登录修改echo dev_a:Init123 | chpasswd chage -d 0 dev_a # dev_b、ops_c 同理注意chage -d 0这个参数很容易被遗漏。没有它初始密码就会一直有效安全要求高的话是不允许的。第二步创建项目目录并设置权限mkdir -p /srv/myapp/logs chown root:devteam /srv/myapp chmod 2770 /srv/myapp chown root:devteam /srv/myapp/logs chmod 2775 /srv/myapp/logs开发组对logs目录有读权限同时可以新建日志文件logs设2775组内可写但比项目根目录稍宽松方便运维读取日志。第三步配置sudo规则visudo -f /etc/sudoers.d/opsteam写入%opsteam ALL(root) /usr/bin/systemctl这里只允许执行systemctl不能执行systemctl后面的自定义参数因为是从白名单命令树判断的所以systemctl restart nginx被允许但systemctl本身不是安全风险。注意别加NOPASSWD这样每次执行sudo还是会要求输入密码审计日志里也能留下记录。7.3 权限验证与结果检查配置完后必须做一次验证。切到dev_a用户试试能否在项目目录里建文件su - dev_a cd /srv/myapp touch test.txt ls -l test.txt如果test.txt属组是devteam说明setgid生效。然后切到ops_c执行sudo systemctl restart nginx系统提示输入密码后正常执行。再试着执行sudo useradd baduser应该被拒绝。这一步验证sudo规则确实生效而不是仅停留在配置文件层面。整个流程走下来就是一次小型的“用户权限初始化”完整闭环。把这套步骤固化成脚本或文档换一台新服务器也能快速复制。8. 常见问题与排错速查表最后整理一份排错速查表。这些都是我在实际环境里遇过、或者在各类服务器问答里高频出现的问题配上排查思路比背命令参数更管用。8.1 用户创建和使用中的高频故障现象可能原因排查命令与解法useradd报错“用户已存在”用户确实已创建或被删除但残留影子条目id 用户名查是否存在检查/etc/passwd和/etc/shadow登录后没有家目录创建时漏了-m或家目录被误删cd ~失败重新创建家目录并chown切到用户后命令找不到su没加-环境变量未加载用su -切换检查用户.bash_profile密码正确但登录被拒账号被锁定、密码过期、SSH禁止密码登录passwd -S 用户名、chage -l 用户名用户无法用sudo不在sudo配置的组里或配置被覆盖groups 用户名、visudo -c检查语法新建文件属组不对目录没设setgid或用户主组不对检查目录权限位是否含2调整后重新chown8.2 涉及UID/GID不一致的坑有次我在一台服务器上把某个业务的部署目录从A用户改成B用户结果忘了处理缓存目录里已经存在的几百个文件业务启动后一直报缓存写入失败。这就是典型的“目录权限改了但存量文件归属没跟着改”。生产环境调整用户归属时一定要执行一遍完整的文件扫描再改find /srv/myapp -user olduser -exec chown newuser:newgroup {} \;8.3 实战中的几条核心经验第一用户管理命令本身不难难的是变更前想清楚影响范围变更后做验证。每次加用户、调权限、删账号都要对应着思考“这个操作会不会影响正在跑的进程”“会不会影响服务读取配置文件的权限”。第二能用组授权就不要单用户授权。组是权限的单位管理一个组的成本远低于逐个用户去排查“谁的权限没给够”。哪怕现在只有一个用户我也建议先建组把用户塞进去。等规模大了再回补组的成本很高。第三sudo规则和人一样会“长胖”。定期清理不再使用的授权是必要的。我自己的习惯是每个季度拉一遍/etc/sudoers和/etc/group里过期账号见到超过三个月没登录的账号就锁掉不确定要不要删的先锁定避免误伤。第四所有变更命令都建议在变更窗口执行并提前写好回滚方案。比如批量usermod之前先导出当前的用户和组信息万一覆盖了某个附加组还能快速恢复。备份命令简单cp /etc/passwd /root/backup/passwd.$(date %F) cp /etc/shadow /root/backup/shadow.$(date %F) cp /etc/group /root/backup/group.$(date %F)这三个文件备份下来用户管理基本就能“悔棋”不需要依赖任何额外的工具。如果你之前只是零散地用过useradd和passwd希望这篇内容能帮你把整套用户管理命令串成一条线。从配置文件开始到命令实操再到批量场景和安全排查每一步都在解决真实运维里的具体问题。下次再接到“帮新同事开个账号”这种需求时你就有了一套标准操作流程而不是临时翻命令。