在 Linux 服务器上摸爬滚打这些年,用户管理是我觉得最基础也最容易被忽视的一环。很多人觉得它不过是 useradd、passwd、chmod 那几个命令,但真到了线上出问题——某个账号突然登不进去了、某个人不小心改了不该改的文件、离职同事的账号还留在服务器上——才发现自己根本没吃透 Linux 用户管理的完整逻辑。这篇文章我会从一个实际运维的视角,把用户与用户组的核心概念、增删改查操作、权限体系、实战配置思路,以及我踩过的一些坑,系统性地过一遍。无论是刚开始学 Linux 的新人,还是需要承担服务器日常维护的开发者、运维同学,应该都能从中拿到可以直接落地的方案。
1. 先搞清楚Linux用户管理到底在管什么
在实际工作里,我见过太多人上来就背命令参数,背完转头就忘。原因很简单——没理解 Linux 用户体系的底层逻辑。Linux 是一个典型的多用户多任务操作系统,用户管理本质上就做两件事:一是让不同的人以不同的身份登录系统,二是让这些身份对文件资源的访问权限处于可控状态。搞懂这两点,后面所有命令都是在做填空题。
1.1 用户的两个身份标识:UID 和 GID
Linux 系统不认识“张三”“李四”这种名字,它只认数字。每个用户都会有一个用户 ID,也就是 UID;同时至少会归属于一个用户组,组也有自己的 ID,也就是 GID。这两个 ID 才是系统判断“你能访问什么”的核心依据。
- root 的 UID 固定是 0,它拥有整个系统最高权限,可以无视绝大多数权限限制;
- 普通用户一般从 1000 开始分配(Ubuntu、CentOS 7 之后都是这个惯例),比如第一个手动创建的用户通常是 1000,第二个是 1001,依次递增;
- 系统服务账号的 UID 通常在 1~999,像 sshd、mysql、nobody 这些,它们存在的意义是让服务以独立身份运行,而不是让真人登录。
这里有一个非常容易被忽略的细节:Linux 内核在做权限校验时只认 UID/GID 数字,不认用户名。所以如果两个用户的 UID 相同,在系统眼里它们就是同一个人,互相能看到对方的文件、能进入对方的家目录。我之前排查过一次“普通用户能访问同事家目录”的事件,最后发现就是创建用户时手抖设置了相同的 UID。这个坑不像权限位冲突那么显眼,但一旦踩中,后果往往很隐蔽。
1.2 用户与组的基本关系
组(group)的作用是批量管理权限。一个用户可以同时属于多个组,但只能有一个主组(primary group)。主组决定你新建文件的默认所属组,附加组(supplementary group)决定你额外能访问哪些资源。
举个例子,你的账号 uid=1001 属于主组 developer,同时被加进了 sudo 附加组。那么你创建的所有文件默认都属于 developer 组,但你可以用 sudo 执行管理员命令。这两个身份互不冲突。设计得合理的团队,通常会把“读权限”分配给某个组,“执行权限”分配给另一个组,通过用户所在组来控制人的权限边界,而不必单独给每个人配一套权限规则。
1.3 用户信息存储的三大配置文件
Linux 下用户信息不是存在数据库里的,而是存在三个纯文本配置文件里。这三个文件必须滚瓜烂熟:
| 文件 | 作用 | 关键字段 |
|---|---|---|
| /etc/passwd | 用户基本信息 | 用户名、密码占位符、UID、GID、注释、家目录、登录Shell |
| /etc/shadow | 用户密码与策略 | 加密密码、密码修改日期、过期时间、锁定状态等 |
| /etc/group | 用户组信息 | 组名、组密码占位符、GID、组成员列表 |
/etc/passwd 每一行用冒号分成 7 段,格式是:用户名:密码位:UID:GID:描述:家目录:Shell。以前密码就直接存在这个文件里,后来才挪到 shadow,所以现在 passwd 里密码位置统一是一个 x 占位符。而 /etc/shadow 只有 root 能读,里面才是真正经过哈希加密的密码串。
我建议各位没事多用 cat /etc/passwd 和 cat /etc/group 翻一翻,比死记任何命令手册都管用。等你一眼能看懂每一行每个字段的含义,用户管理就已经学会一大半了。至于影子文件 /etc/shadow,普通用户没权限看,root 查看时也要小心,别把加密串泄露出去。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 用户与用户组的增删改查:命令实操全解析
这一章按“增、改、删、查”四条线,把高频命令串起来讲。我带新人时最常强调一句话:命令可以慢慢记,但每个命令的“副作用”必须提前知道——比如 useradd 到底建了哪些东西、userdel 会不会删家目录,这些坑我都踩过,提前说清楚能帮大家少走弯路。
2.1 创建用户:useradd 别只记一个裸命令
新手最爱犯的错误是直接执行 useradd zhangsan,然后发现用户建好了,但没有家目录,登录也进不去。原因在于不同发行版对 useradd 默认行为的定义不一样,有的发行版默认帮你建家目录,有的默认不建。最稳妥的姿势是显式指定参数:
bash复制useradd -m -d /home/zhangsan -s /bin/bash -c "Zhang San" zhangsan
常用参数说明:
-m:创建用户的同时创建家目录;-d 路径:手动指定家目录位置,默认是 /home/用户名;-s Shell:指定登录 Shell,一般用 /bin/bash,如果想让账号不能登录就设 /sbin/nologin;-c 注释:写入 /etc/passwd 第五段的描述信息,用于标注这个账号是谁、干什么用的;-u UID:手动指定 UID;-g 组名或GID:指定主组;-G 组1,组2:追加附加组,多个组用逗号分隔;-e 日期:指定账号过期日期,格式 YYYY-MM-DD。
我在给项目组批量建账号的时候,固定用一行命令:useradd -m -s /bin/bash -G project -c "姓名-岗位" 用户名。这样建出来的账号结构统一,后续审计也方便。注意 -G 后面跟的附加组如果不存在,命令会直接报错,所以要先把组建好再建用户,顺序不能反。还有一点,-m 和 -d 经常配套使用,-d 指定自定义路径时,-m 会让你指定的目录被自动创建,否则就算指定了路径,目录也可能不会生成。
2.2 修改用户信息:usermod 才是日常主力
用户创建之后,很多信息都需要调整,usermod 就是干这个的。它跟 useradd 的参数非常相似,比如 -l 改用户名、-d 改家目录、-s 改 Shell、-g 改主组、-aG 追加附加组。
重点说几个容易被误解的参数:
-L锁定用户:在 /etc/shadow 的密码前面加上感叹号,让密码失效,用户无法登录;-U解锁用户:把加上的感叹号去掉,恢复密码登录;-aG与-G的区别:-G是“把附加组设置成这些组”,属于覆盖操作;-aG是“在原有附加组基础上追加”。如果直接用-G而不带-a,会把用户从原来的附加组里挤出去,这是线上事故的高发点,必须留心。
实际案例:某次同事想把一个临时外包账号从 project 组挪到 ops 组,执行了 usermod -G ops zhangsan,然后我发现 zhangsan 的 sudo 权限也没了,才意识到他的 sudo 权限也是通过附加组方式加的,这个命令把原来的 sudo 组覆盖掉了。所以只要你不想动原来的组,一律用 usermod -aG 新组名 用户名,千万别省那个 a。
2.3 删除用户:userdel 的收尾工作别漏了
删除用户执行 userdel zhangsan,只是把 /etc/passwd、/etc/shadow、/etc/group 里的记录删掉。用户的家目录、邮件池、属于他的文件并不会自动清理。要想连家目录一起删,就要加 -r:
bash复制userdel -r zhangsan
但注意,这个 -r 只删家目录和 mail 池,用户在其他位置创建的文件(比如 /data、/tmp、自己的代码目录)是不会动的。所以生产环境里的规范做法是:删账号之前,先用 find / -user zhangsan 把属于这个用户的文件清单导出来,确认哪些要迁移、哪些要删除,再执行删除操作。我以前在清理离职人员账号时,就在 /opt 底下找到一大堆历史项目代码,要不是先做了文件盘点,这些代码就会变成一堆 nobody 文件,以后归属不明会非常麻烦。
2.4 用户组管理:建组、删组、加人、踢人
组的命令同样也是四个方向:groupadd 建组、groupmod 改组、groupdel 删组、gpasswd 管理组成员。
groupadd ops直接建组,-g可以指定 GID;建议给组也规划固定 GID 范围,方便配合文件权限;gpasswd -a 用户名 组名把用户加进组;gpasswd -d 用户名 组名把用户移出组;groupdel 组名删组,注意如果一个组是某个用户的“主组”,直接 groupdel 会失败,报cannot remove the primary group。
这里还要提一个高频查询命令:id。执行 id zhangsan 会显示用户的 UID、GID 和所有附加组,这是排查权限问题时的第一把钥匙。再加上 who、w、last、lastlog 这类登录信息查询命令,基本能掌握系统的用户动态。我一般排查用户相关问题时,先跑 id,再跑 lastlog,很快就能定位到是身份配置的问题还是登录行为的问题。
3. 权限体系:用户管理里最容易翻车的部分
创建用户只是第一步,真正让“用户管理”有意义的是权限边界。Linux 的权限体系以“人 → 组 → 其他人”三层模型为基础,再叠加 umask、特殊权限位、ACL 这些进阶机制。下面从最常用的权限表示讲起。
3.1 权限位的表示与计算:rwx 和 421
每个文件或目录都有一组权限位,分为三段:所有者权限、所属组权限、其他人权限。每段里可能包含 r(读)、w(写)、x(执行)三个符号。用 ls -l 查看文件时,第一列形如 -rwxr-xr--,就表示所有者可读写执行,组可读可执行,其他人只能读。
数字表示法是对应的换算:r=4,w=2,x=1,把三段数字拼起来就是 chmod 的参数。比如上面的权限就是 754(7=4+2+1,5=4+1,4=4)。这是新手最容易理解错的地方——有人说 777 就是所有权限,其实 777 意味着任何用户都能读、写、执行,对普通文件来说几乎等于裸奔。给文件 777 之前,先问自己一句:这个文件真的需要让所有人生成、修改和执行吗?
目录权限和文件权限不一样,这一点很多人栽跟头。目录的 r 表示能列出目录里的文件名,w 表示能在目录里创建或删除文件,x 表示能进入目录。所以如果你只有目录的 r 而没有 x,你会看到 ls 列出文件名,但一 cd 进去就提示 Permission denied。反过来,你只有 x 没有 r,可以进目录,但 ls 是空的,不过知道确切文件名的时候可以直接读,比如 cat /secretdir/data.txt 是可以成功的。这种坑在配置 nginx、tomcat 目录时非常常见,建议遇到权限问题时先理清自己对目录的三个权限到底分别有什么。
3.2 chmod、chown、chgrp 实战
chmod改权限:chmod 750 文件或chmod u+x 文件;递归操作加-R,慎用;chown改所有者:chown zhangsan 文件或chown zhangsan:dev 文件(同时改所有者和所属组);chgrp改所属组:chgrp dev 文件,等价于chown :dev 文件。
我在生产实践中强烈建议给目录按“所有者 + 所属组”的组合来管理,而不是一股脑给其他人开权限。比如项目目录统一 chown -R devuser:project /data/project,然后 chmod 2770 /data/project,这样只有项目组成员能读写,其他人一律进不来。目录上加的 2 是特殊权限位,下面详细说。
3.3 umask:决定新文件的默认权限
umask 是很多人忽略但实际影响很大的参数,它规定了“新创建文件或目录时,默认扣掉哪些权限”。直接执行 umask 会显示结果,常见值是 022 或 002。
计算方式很简单:文件的默认权限最大值是 666,目录是 777,用最大值减掉 umask 就是实际权限。所以 umask 022 时,新建文件的权限是 644(666-022),目录是 755(777-022)。umask 002 时,新建文件是 664,目录是 775,这个设置通常用于需要组内协作的环境,方便同一组的人互相修改文件。
注意:文件默认没有执行位,所以即使你算出来一个可执行的效果,最终也会去掉 x。这是系统设计上防止误生成可执行文件的一种保护。很多开发在服务器上解压 tar 包出来文件权限偏大或偏小,实际就是 umask 环境不一致导致的。
3.4 ACL 扩展权限:让权限精确到一个人
普通权限模型只能针对“所有者、组、其他人”三层控制。如果有一个文件想给 A 组读、给 B 组写、给 C 个人执行,用传统的 chmod 是没法精确表达的,这时候就需要 ACL(Access Control List)。
用 setfacl 给指定用户或组设置权限:
bash复制setfacl -m u:zhangsan:rwx /data/project
setfacl -m g:dev:rx /data/project
查看用 getfacl /data/project。设置完 ACL 后,ls -l 权限位后面会多一个加号,比如 drwxrwx---+。需要注意的是,ACL 是在基础权限之上做追加,设置后基础权限不一定能反映全部规则,排查时一定要结合 getfacl 看全量规则,别只看 ls -l。ACL 还有一个好处是它天然支持“多个组、多个人”叠加,比传统权限灵活太多,适合目录共享、多人协作这类场景。
4. 实战场景:从零搭建一套多用户服务器权限体系
到了这章,用一个具体场景把所有知识串起来。假设你是一家小公司的运维,刚拿到一台全新的 Linux 服务器,需要建出这样一套用户体系:
- 运维组 ops:2 人,具备服务器的管理权限;
- 开发组 dev:3 人,能读写项目代码目录,但不能执行系统管理命令;
- 实习生组 intern:1 人,只能看代码,不能改任何东西;
- 系统默认的 root 账号只在本地登录,远程一律禁止。
下面按步骤走一遍完整流程。
4.1 用户规划与分组设计
先建组,再建用户。组规划如下:
| 组名 | GID | 用途 |
|---|---|---|
| ops | 3001 | 运维组 |
| dev | 3002 | 开发组 |
| intern | 3003 | 实习生组 |
执行:
bash复制groupadd -g 3001 ops
groupadd -g 3002 dev
groupadd -g 3003 intern
建用户时额外注意:运维账号要加入 sudo 组,开发账号加入 dev 组,实习生账号只用 intern 组即可,且不能加入任何 sudo 组成员。
4.2 批量创建用户与初始密码设置
一个个 useradd 太慢,可以写个小循环脚本:
bash复制for name in zhangsan lisi wangwu
do
useradd -m -s /bin/bash -g dev -c "dev-$(date +%F)" "$name"
echo "$name:初始密码123456" | chpasswd
passwd -e "$name"
done
脚本里做了三件事:创建用户、用 chpasswd 批量设置初始密码、用 passwd -e 强制用户首次登录时修改密码。这是批量建号的标配流程,既保证账号可用,也避免长期共用初始密码的安全隐患。
开发人员需要访问项目目录 /data/project,所以:
bash复制mkdir -p /data/project
chown -R root:dev /data/project
chmod -R 2770 /data/project
这样 /data/project 的组所有者是 dev,目录具备 setgid 位(2),组内成员有读写执行权限,其他用户无法访问。setgid 位的额外效果是:目录下新建的文件和子目录会自动继承目录的所属组,这对团队协作极为重要。否则 dev 成员各自建文件,新文件所属组是各自主组,组内其他人就会互相访问不了。
4.3 sudo 授权精细化配置
运维用户能执行管理员命令,靠的是 sudo 组成员身份:
bash复制usermod -aG sudo zhangsan
usermod -aG sudo lisi
但“能 sudo”和“能执行所有命令”是有区别的。sudo 的规则在 /etc/sudoers 里配置,这个文件必须通过 visudo 编辑,它会检查语法,防止写错导致系统 sudo 全失效。默认配置里 %sudo ALL=(ALL:ALL) ALL 已经允许 sudo 组执行所有命令。
如果你希望更精细化,可以单独给 dev 组开放某几个特定命令,比如允许开发人员只执行指定服务的重启:
bash复制%dev ALL=(ALL) /usr/bin/systemctl restart webapp
这样开发人员可以重启指定服务,但不能改 root 密码、不能修改系统关键文件。配置完成后,还有一个小技巧:想让用户执行 sudo 时不用输密码,可以加 NOPASSWD:,比如 %dev ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart webapp,但生产环境慎用,免密权限过大容易变成安全漏洞,建议只在受控的专用跳板机上用。
4.4 锁定与清理不再使用的账号
系统上会有一些不再使用但还没删除的账号。比如离职员工的账号,规范做法是先锁定,观察一段时间确认没有在跑的任务,再删。
bash复制passwd -l zhangsan # 锁定账号
usermod -e 2024-01-01 zhangsan # 设置过期时间
lastlog | grep zhangsan # 查看最近登录记录
锁定和删除的取舍:锁定只是让密码失效,文件还在,用户可以临时恢复;删除则会把用户从系统中整个移除。我的经验是“先锁再删”:先锁定 30 天,确认无任何 cron 任务、常驻进程和同事反馈需要,再 userdel -r 彻底清理。别忘了清理前先查 crontab -l -u 用户名 和 ps aux | grep 用户名,否则某些定时任务或守护进程可能在你删号后变成孤儿进程,长期占用资源。
5. 常见故障与排查技巧实录
这一章整理了我自己这些年碰到的高频问题,每一条都有人在社区反复问过。
5.1 用户加了 sudo 组,sudo 还是提示不在 sudoers 中
先看现象:执行 sudo 时提示 xxx is not in the sudoers file. This incident will be reported.。最常见原因是用户不属于 sudo 组,或者 /etc/sudoers 里没有显式规则。很多误操作是用 usermod -G sudo 而不是 -aG sudo,结果把用户原有的附加组覆盖了,你以为加了 sudo,实际可能加错了组或没加进去。
排查步骤:先 id 用户名 看 Groups 里有没有 sudo;如果没有,执行 usermod -aG sudo 用户名;如果有了还报错,检查 /etc/sudoers 是否被改坏,用 visudo -c 做语法检查。
5.2 useradd 创建后用户无法登录
表现是输入密码后直接退回去,或者提示 User not known to the underlying authentication module。多半原因有:
- 忘了
-m,家目录不存在,登录 Shell 无法设置 HOME; - Shell 设置成了 /sbin/nologin,交互登录会失败;
- /etc/shadow 中该用户密码字段有问题,比如密码策略被 chage 限制。
排查顺序是:ls -ld /home/用户名 看家目录是否存在且属主正确;grep 用户名 /etc/passwd 看 Shell 字段;grep 用户名 /etc/shadow 看密码策略。修复常见方案是:mkdir 家目录,chown 用户名:组名 家目录,然后 usermod -s /bin/bash 用户名。
5.3 删除用户后,文件所有者的 UID 没清理
userdel -r 删掉用户后,他在别处的文件依然保留,但 ls -l 显示所有者变成一个数字,因为 UID 没有对应用户名了。这时想再删这些文件,普通账号没权限,得用 root。
处理方式:按需把文件 chown 给现存用户,或者直接删除。如果文件特别多,用 find / -uid 1001 -exec ls -l {} \; 来找。我通常在清理完账号后都会跑一遍这个命令,避免孤儿文件长期占用磁盘空间或留下权限隐患。
5.4 /etc/passwd 或 /etc/group 被人为改坏
这种情况我遇到过两回,一次是手抖在 passwd 文件里多删了一个冒号,另一次是 group 文件里成员列表写错。后果就是系统各种奇怪问题:有的用户无法登录、有的服务起不来、sudo 也全坏。
处理教训是:改这两个文件前一定要先备份,cp /etc/passwd /etc/passwd.bak。Linux 本身提供了 vipw 和 vigr 命令来安全编辑这两个文件,编辑时会自动加锁、校验语法。我强烈建议别用 vim 直接编辑,哪怕你是资深用户,也用 vipw 和 vigr。绕开校验的代价很可能是连 root 都登不进去,到时候只能进单用户模式救援,劳心费力。
5.5 排查思路快速表
| 症状 | 第一步命令 | 常见根因 |
|---|---|---|
| 用户无法登录 | tail -f /var/log/auth.log 或 journalctl -u ssh | 密码错、账号锁定、Shell 无效 |
| sudo 不可用 | id 用户名 | 未加入 sudo 组、sudoers 规则错误 |
| 权限不足 | ls -ld 目标路径 | 所有者或组不对、ACL 覆盖、特殊权限位问题 |
| 无法创建文件 | mount 看挂载点权限 + umask | 目录权限不足、磁盘只读 |
| 明明有权限却不行 | getfacl 路径 | ACL 规则遗忘、特殊权限位冲突 |
最后再分享一条我的心得:用户管理看似是一堆命令,核心其实是“最小权限原则 + 可审计原则”。最小权限意思是给用户的权限,刚好够干活就行,绝不多给;可审计意思是每一次建号、改组、删号都要有日志、有备注、有流程。我自己每次操作完用户,都会顺手把 /etc/passwd、/etc/shadow、/etc/group、/etc/sudoers 四个文件的改动时间做个记录,月底复查一遍。这个习惯一开始坚持起来麻烦,但时间长了会发现,它能帮你省下大量排查“谁动了服务器”的时间。希望这篇文章能帮你把用户管理从“背参数”变成“搭体系”。
