1. 用户管理到底在管什么:先看清 Linux 多用户设计的底层逻辑
刚接触 Linux 的人,最容易把“用户管理”理解成“创建账号、设置密码”这么简单的事。实际上,用户管理是 Linux 整个权限模型的地基,你后面遇到的权限报错、服务起不来、文件删不掉,八成都能回溯到用户配置上。
Linux 是一个天然的多用户操作系统。这意味着同一台服务器上,可以同时有十几个不同身份的人登录操作,他们互相之间不干扰,也不能随便读写对方的文件。这套隔离机制靠的就是用户(user)和用户组(group)两层身份体系。用户是你作为个体的身份凭证,用户组则是一组用户的集合,用来批量授予权限。你可以把用户组理解成“部门”,把用户理解成“员工”——某个文件允许“财务部”访问,那就等于财务部里所有人都有权限。
我们在生产环境里管理服务器时,几乎每天都要和这些概念打交道。部署一个 Web 服务,得新建一个专用账号来跑进程,而不是图省事直接用 root;多个运维同事要登录同一台机器,最好统一加到一个 ops 组里再统一配 sudo 权限;某个同事离职了,需要立刻禁用他的账号但不能急着删,因为他的文件可能还有审计价值。
这套体系看着简单,真正用好的关键在于理解三个文件:/etc/passwd、/etc/shadow、/etc/group。很多运维老手面试时爱问这三个文件,不是考背诵,而是考你是否真正理解用户管理的核心机制。后文我会逐个拆开讲清楚。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 动手之前的必修课:用户组、用户文件与权限模型
2.1 用户组是谁,为什么 Linux 一定要有它
先聊用户组。你在 Linux 里执行 ls -l 查看文件属性时,看到的第三列和第四列分别就是文件所有者和所属组。组是权限管理的最小批量单位,没有组的话,你要给 20 个人放行某个目录,就得一条条去设置 20 个用户的 ACL,那显然不现实。
每个用户创建时,Linux 默认会创建一个和他用户名同名的私有组(user private group)。比如你创建了一个叫 zhangsan 的用户,系统会顺带建一个 zhangsan 组,这个组默认只有 zhangsan 一个人。这种设计的好处是:每个用户新建文件时,默认所属组就是同名的私有组,文件默认权限不会暴露给其他用户,安全性更好。
创建用户组用 groupadd,删除用 groupdel,把用户添加到附加组用 usermod -aG。这里强调一下“附加组”和“主组”的区别。一个用户必须有一个主组(primary group),同时可以加入多个附加组(supplementary group)。你输入 id 命令时,能看到类似 uid=1000(zhangsan) gid=1000(zhangsan) groups=1000(zhangsan),1001(docker) 的输出,gid 后面那个就是主组,groups 里列出的其他组是附加组。
刚开始用 Linux 的人经常犯一个错误:以为把用户加进 docker 组之后,用户的主组就变成 docker 了。不是的,主组不变,只是多了一个附加组身份,能访问 docker 组有权限的资源。理解这个区别,后面排查权限问题时能少走很多弯路。
2.2 /etc/passwd、/etc/shadow、/etc/group 三个文件逐字段解读
这部分我建议每个搞 Linux 的人都彻底过一遍。虽然现在有 useradd 之类的命令帮你写文件,但服务器突然出问题时,你还是要手动去看这些文件的。机器不会说谎,命令可能配置错,文件内容就是最终的真相。
/etc/passwd 每一行代表一个用户,用冒号分隔成 7 个字段:
bash复制zhangsan:x:1000:1000::/home/zhangsan:/bin/bash
依次是:用户名、密码占位符(真正的密码在 shadow 里,这里显示 x 表示已加密存储)、UID、主组 GID、用户备注信息(GECOS 字段,通常存姓名或电话)、家目录路径、登录 Shell。需要注意,/bin/nologin 表示这个用户不能登录系统,通常用于服务账号,比如 nginx、mysql 用户默认都是 nologin。
/etc/shadow 保存加密后的密码和密码策略信息,只有 root 或有 sudo 权限的人才能读取。它的字段更多,重点是前几个:用户名、加密密码、最后一次修改密码的日期(从 1970 年 1 月 1 日起的天数)、密码最少使用天数、密码最长使用天数、密码过期前警告天数、密码过期后的宽限天数、账号失效日期。
/etc/group 保存组信息,格式比较简单:组名、组密码占位符、GID、组成员列表(逗号分隔的附加组成员)。
用命令改用户时,建议操作完顺手 cat 一下这几个文件确认效果。我之前排查过一个诡异问题,用户明明在 docker 组里却无法执行 docker 命令,最后发现是 /etc/group 里的成员列表被手写改坏了,多了一个空格,导致系统解析失败。这种东西只有看文件才能发现。
2.3 权限模型的三个数字和四种对象
理解用户管理,还要搞清楚权限。Linux 的权限模型说白了就是“三种身份 × 三种权限”。三种身份是属主(u)、属组(g)、其他用户(o),三种权限是读(r=4)、写(w=2)、执行(x=1)。用数字表示时,把三种权限相加,比如 7=4+2+1 表示读写执行,5=4+1 表示读和执行,6=4+2 表示读写。
新手总是记不住 755、644 这些数字组合,我提供一个直观的方法。常见的目录权限是 755,意思是主人可以随便改,其他人只能看和进入;常见的文件权限是 644,意思是主人可以改,其他人只能看,不能执行。如果你部署了一个脚本,发现“明明给了执行权限还是跑不起来”,大概率是脚本的解释器路径写错了,或者脚本所在的目录没有执行权限——Linux 对目录的执行权限(x)实际上对应着“能否进入目录并访问其中文件”的能力,这是一个非常容易被忽略的细节。
权限检查的先后顺序也要说清楚。Linux 检查权限时按顺序来:先看你是不是文件属主,是的话只按属主权限判断;不是的话再看你是不是属组成员,是的话只按属组权限判断;如果两者都不是,才看“其他用户”的权限。很多人以为权限会叠加,比如既是属主又是组成员,就会取两者权限的并集。这是错的,Linux 不会叠加,它只认命中的第一个身份。理解这一点,遇到“为什么我加了组还是没权限”的问题就能快速定位。
3. 核心实操:从新建用户到批量配置的完整流程
3.1 useradd vs adduser:到底该用哪个
网上教程经常混用 useradd 和 adduser,新手很容易被搞糊涂。简单说,在 Debian/Ubuntu 系系统里,adduser 是 useradd 的友好封装脚本,它会交互式地引导你设置家目录、密码、Shell 等;useradd 则是原生的系统命令,参数多、更灵活,但不会帮你创建家目录和生成默认配置。在 CentOS/RHEL 系里,adduser 其实就是指向 useradd 的软链接,两者没有区别。
我的习惯是:生产环境统一用 useradd 加参数手动控制全部细节,不用 adduser 的交互式引导。原因是交互式不利于脚本自动化,也不利于你对每个配置项精确掌控;但如果是本机临时加个人用账号,adduser 更省事。
一个标准的生产级创建命令长这样:
bash复制useradd -m -d /home/zhangsan -s /bin/bash -c "Zhang San - Devops" -u 1001 -g zhangsan -G docker,ops zhangsan
逐项解释一下:
- -m:创建用户时同时创建家目录。
- -d:指定家目录路径,默认是 /home/用户名。
- -s:指定登录 Shell,要给 Shell 就填 /bin/bash,这是普通用户的默认;服务账号建议填 /sbin/nologin。
- -c:备注信息,一般写姓名或用途,后续用 finger 或 grep passwd 文件时方便识别。
- -u:手动指定 UID。多台服务器之间要做文件同步、NFS 共享时,必须保证用户 UID 一致,否则文件属主会显示成数字而不是用户名。这是很多存储项目踩坑的高频原因。
- -g:指定主组。
- -G:指定附加组,可以逗号分隔多个组。
创建完用户后,立刻设置密码:
bash复制passwd zhangsan
然后验证一下成果:
bash复制id zhangsan
ls -ld /home/zhangsan
如果输出 UID、GID、家目录都没问题,说明创建成功。这里我要强调一个用户管理的行业习惯:创建用户时把 UID 规划好,而不是完全交给系统自动分配。比如运维组用 1000-1010 段,开发组用 1011-1020 段,这样后续做权限审计、日志追溯时会非常方便。很多企业级的 LDAP 或 Ansible 用户管理方案,本质上也是在做 UID 的集中规划和分配。
3.2 usermod 和 userdel:修改、锁定与删除用户时千万别手滑
用户创建之后,修改信息用 usermod。常用的几个修改场景:
bash复制# 把 zhangsan 加入 sudo 组(Ubuntu 系)或 wheel 组(CentOS 系)
usermod -aG sudo zhangsan
# 修改用户的主组
usermod -g devgroup zhangsan
# 修改用户的登录 Shell
usermod -s /bin/bash zhangsan
# 锁定账号(禁止登录但保留数据和配置)
usermod -L zhangsan
# 解锁账号
usermod -U zhangsan
特别提醒:修改附加组时,如果忘了加 -a 参数,会直接覆盖掉用户原有的附加组列表。比如用户本来在 docker、ops 两个组里,你执行 usermod -G sudo zhangsan,就会发现用户的 docker 和 ops 组全没了,只剩 sudo。这是一个真实环境中经常发生的“低级但严重”的操作事故,建议每次改完马上用 id zhangsan 确认。
删除用户用 userdel。默认情况下 userdel 不会删除用户的家目录和邮件目录,如果确认这个账号没用了,建议连家目录一起清掉:
bash复制userdel -r zhangsan
但注意,这里不是所有情况都建议加 -r。如果你删除的用户是一个历史项目的主要维护者,保留他的家目录和文件,对后续审计、备份恢复都有价值。比较稳妥的做法是:先 usermod -L 锁定账号,观察一段时间,确认没有影响后,再导出或归档家目录,最后才考虑删除。我见过太多人一上来就 userdel -r,结果三个月后要追溯某个变更记录,只能翻备份,极其被动。
3.3 批量创建用户:用脚本而不是手工一条条敲
当你有几十个用户要一次性创建时,手工敲命令不现实。这时可以写一个简单脚本,用 newusers 命令批量导入。newusers 是 Linux 自带的工具,它能从一个文本文件里读取标准格式的用户信息并批量创建。
先准备一个 users.txt 文件,每行格式和 /etc/passwd 一样:
bash复制zhangsan:x:1001:1001::/home/zhangsan:/bin/bash
lisi:x:1002:1002::/home/lisi:/bin/bash
wangwu:x:1003:1003::/home/wangwu:/bin/bash
然后要批量设置密码,还需要准备一个 passwd.txt 文件,格式是“用户名:密码”:
bash复制zhangsan:初始密码123
lisi:初始密码456
wangwu:初始密码789
创建组 + 导入用户:
bash复制groupadd zhangsan && groupadd lisi && groupadd wangwu
newusers < users.txt
chpasswd < passwd.txt
执行完确认一下:
bash复制awk -F: '$3>=1000 {print $1,$3,$7}' /etc/passwd
不过要提醒一句,批量创建用户时“明文密码写在文件里”本身就是一个安全隐患。生产环境我建议过程账号都先用随机密码,然后通过密钥认证登录,密码只在紧急控制台场景下使用。至于脚本中密码文件的存放,务必放在只有 root 能读的目录下,用完立刻销毁。
3.4 用户切换与身份提权:su、sudo 的正确打开方式
日常操作中,你不会一直用 root 工作,而是用普通用户登录,在需要时再切换或提权。这里涉及 su 和 sudo 两个工具,它们的区别非常关键。
su 是切换用户(switch user),默认切换到 root,需要输入目标用户的密码。执行 su - root 会同时切换用户和环境变量(包括当前目录、PATH 等),执行 su root 则只换身份不换环境。生产环境我不建议用 su,因为它意味着你要分享 root 密码给多人,密码每多一个人知道,泄露面就大一分。
sudo 是“以其他用户身份执行命令”,它只需要输入当前用户自己的密码,而且可以通过 sudoers 文件做精细授权:谁能用、能用哪些命令、在哪台机器上能用。这是目前企业服务器管理的标准做法。
给用户开通 sudo 权限,在 Ubuntu 系是把用户加进 sudo 组,CentOS 系是加进 wheel 组:
bash复制usermod -aG sudo zhangsan
如果要更精细地控制,可以直接编辑 /etc/sudoers 文件。注意这个文件语法极其严格,写错了会导致 sudo 全部失效,所以建议用 visudo 命令来编辑,它会在保存前做语法检查。比如只允许 zhangsan 执行 systemctl 命令而不给 root shell:
bash复制zhangsan ALL=(root) /usr/bin/systemctl
这个配置的意思是:zhangsan 可以在任何主机上,以 root 身份,执行 /usr/bin/systemctl 命令。而 NOPASSWD 选项可以让某个用户执行免密 sudo,适合自动化脚本场景,但安全性风险也随之上升,一般不建议直接在 sudoers 里给普通用户配 NOPASSWD ALL。
4. 权限与安全加固:用最小权限原则降低服务器风险
4.1 服务账号为什么要用 nologin,而不是删掉
前面多次提到服务账号。所谓服务账号,就是 Apache、MySQL、Redis 这些服务运行时使用的专用账号。它们存在的意义是隔离权限:服务出了漏洞,攻击者拿到的也是这个低权限账号,而不是 root。
创建服务账号时,一个非常重要的原则是:不要登录 Shell。所以标准做法是:
bash复制useradd -r -s /sbin/nologin -d /var/lib/myapp myapp
-r 表示创建系统账号,UID 通常会落在系统保留区间(小于 1000),不会出现在登录界面上。配合 -s /sbin/nologin,即使有人拿到了这个账号的密码,也没法通过 SSH 登入。有些软件包安装时已经自动创建了类似 mysql 或 nginx 的账号,你去看 /etc/passwd,它的 Shell 栏一定是 /sbin/nologin,这说明安装包在安全性上已经做了处理。如果你自己部署了一个自定义服务,就务必照这个标准来,不要图省事用 root 跑。很多初学容器和 Linux 的人习惯用 root 跑一切服务,这在本地开发可以,一旦上了生产环境,隐患极大。
4.2 避免直接使用 root:给 root 加锁还是限制 SSH
很多服务器安全事件,都和 root 账号被暴力破解有关。如果你打开服务器的 /var/log/auth.log,几乎每天都能看到大量来自陌生 IP 的 SSH 登录尝试,它们尝试的默认用户名就是 root。所以生产环境的第一条硬性原则:禁止 root 通过 SSH 直接登录,改用普通用户加 sudo 提权。
具体做法是修改 SSH 配置文件 /etc/ssh/sshd_config:
bash复制PermitRootLogin no
修改后执行 systemctl restart sshd 让配置生效。但改完之前,一定要先确认你的普通用户已经具备 sudo 权限,否则一旦退出 root 登录,你就发现自己被锁在外面了。这是一个极其经典的翻车场景,我在培训时讲过很多次,但每年还是有人中招。
另一个常见操作是修改 SSH 默认端口,比如把 22 改成 2222。这不能真正阻止恶意攻击,但能显著减少被扫描命中的概率。如果你的服务是暴露在公网上的,我还强烈建议开密钥登录:
bash复制ssh-keygen -t ed25519
ssh-copy-id zhangsan@your-server-ip
然后关闭密码认证 PasswordAuthentication no,这样才能从根本上防止暴力破解。Linux 用户管理的终极目标不是“多创建一个用户”,而是“让每个用户都有刚好够用的权限,不多也不少”。
4.3 UID 0 用户审计:找出隐藏的管理员
用户管理里有个隐蔽但危险的点:普通用户如果被修改成 UID 0,他就拥有了和 root 同等的特权。有些攻击者拿到 root 权限后,会创建一个 UID 为 0 的新用户,作为持久化后门。这种账号不会显示为明显的 root,但实际权限等同 root。
排查方法很简单,一条命令找出所有 UID 0 的用户:
bash复制awk -F: '$3==0 {print $1}' /etc/passwd
正常情况下,输出应该只有 root 一行。如果出现其他用户名,就要立刻检查它是什么时候出现的、为什么会存在。同理,检查所有能用 Shell 登录的用户,可以用:
bash复制awk -F: '$7 ~ /bash|sh/ {print $1,$7}' /etc/passwd
这个习惯建议每个月做一次,和查看日志、检查磁盘空间一起纳入日常巡检清单。安全不是装一个防火墙就万事大吉,很多风险就藏在你看似正常的用户配置里。
5. 常见问题与排查技巧实录
5.1 用户删不掉 / 加不进组的典型报错
遇到 userdel 报错说“userdel: user xxx is currently used in process xxx”,说明这个用户有进程正在运行。你不能直接强删,先找到并停止相关进程:
bash复制ps -u zhangsan
kill -9 进程PID
如果这个用户确实没有业务在跑,但进程列表里还是显示有残留,可能是某些僵尸进程或者系统服务以该用户身份在运行,需要进一步排查。比如用户跑了一个 systemd 服务,你需要先 stop 对应的服务单元,再回来删用户。
加不进组的报错通常是 group not found。检查一下组名是否存在,组名写没写错,特别是在 CentOS 系统上,很多人的附加组写成 sudo,但 CentOS 的管理员组其实是 wheel。
5.2 登录后 Shell 不对,或者家目录被占满,怎么处理
用户登录后 Shell 不对,比如明明创建时指定了 /bin/bash,结果显示的还是 sh,常见原因是 /etc/passwd 里用户的 Shell 字段被改过,或者是用户自己的 ~/.bash_profile 里写了切换 Shell 的逻辑。用 usermod -s /bin/bash 用户名 重新设置即可。
家目录空间不足是另一个高频问题。默认家目录在 /home 分区,如果服务器磁盘规划时只给 /home 分了很小的空间,用户一放文件就满了。解决思路有两个:一个是把 /home 软链接到数据盘;另一个是用 usermod -d 把用户家目录指到新的存储路径,再用 mv 把原数据迁移过去:
bash复制mkdir -p /data/home/zhangsan
usermod -d /data/home/zhangsan zhangsan
mv /home/zhangsan/* /data/home/zhangsan/
chown -R zhangsan:zhangsan /data/home/zhangsan
注意迁移数据前一定要确认业务没有正在写入,否则会丢数据。做完后重新登录并执行 pwd 验证当前目录,再确认一下新家目录的权限和属主是否正确。
5.3 密码过期与 root 密码找回问题
企业环境经常要求用户定期改密码,你可以在 /etc/login.defs 里控制全局策略,也可以对单个用户设置过期时间:
bash复制chage -M 90 zhangsan # 密码 90 天后过期
chage -W 7 zhangsan # 过期前 7 天开始提醒
chage -l zhangsan # 查看密码策略
如果用户的密码已经过期,登录时会提示必须修改密码。但有时候用户收到了“密码已过期”的提示,却不知道如何修改,告诉他在命令行执行 passwd 命令即可。
root 密码忘了是运维人最紧张的场景之一。如果你有物理控制台或云厂商的控制台 VNC,可以通过进入单用户模式重置密码,但不同发行版操作方法差异很大。更好的方式是提前配置好 sudo 用户,避免 root 密码丢失导致完全进不去系统。Linux 的很多设计都是这样,做好“预防”远比事后“急救”省心,用户管理尤其如此。
5.4 授权后权限不生效的两大原因
用户明明加进了某个组,执行对应命令还是提示权限不够,这种问题绝大多数是两种原因。
第一种,用户没有重新登录。组身份是在登录时加载的,你 usermod -aG docker zhangsan 之后,zhangsan 如果没退出重新登录,当前会话里是不会带上新组的。执行 id 命令可以看到,groups 列表里没有 docker。这种情况让用户退出重登或者执行 newgrp docker 临时切换即可。
第二种,权限模型命中顺序问题。前面说过,Linux 权限检查按属主、属组、其他用户依次命中,不叠加。假设某个文件属主是 root,属组是 docker,权限是 640。zhangsan 是 docker 组成员但不是属主,那么他命中的是“属组”这条规则,权限是 r--,正常能读。但如果 zhangsan 也是文件的属主(或者文件属主恰好是 zhangsan),那系统会先检查属主权限,如果属主权限是 600,那么即使在 docker 组里,也只能按属主的 600 权限来算,这时他会发现“我明明是组的成员,为什么反而没权限了”。这种问题只能靠调整属主、属组和权限三者关系来解决,加组成员没有用。
6. 多用户环境下的协作与权限规划建议
6.1 用组而不是用人:权限分配的长期维护之道
在实际服务器维护中,我发现一个高效率的协作模式:把权限绑到组上,而不是绑到单独的用户上。比如运维组统一加入 ops 组,研发组统一加入 dev 组,某个目录允许 ops 组读写、dev 组只读。这样人员变动时,只需要把用户的附加组成员调整一下,不用去改文件的属主和权限位。相反,如果你给每个用户单独设置 ACL,刚开始觉得灵活,后来会发现维护成本越来越高:几十个用户,几百个目录,属主权限东一块西一块,根本说不清谁有什么权限。
有一个常用但偶尔会被忽略的命令是 id,它可以快速查看用户当前的身份和所属组,排查权限问题时逐步执行 id 用户名、groups 用户名、namei -l 路径,就能很快定位问题出在哪个环节。
6.2 用户管理经验谈:怎么规划一台新服务器的用户体系
每次新装一台 Linux 服务器,我的标准动作是这样的:先规划好哪些人需要登录、他们属于哪些组、分别需要什么权限;然后创建组、创建用户、配置 sudo;接着禁用 root 远程登录;最后把 SSH 公钥部署好,测试一遍普通用户能否正常登录、能否提权。
把这一套整理成 Ansible 脚本或 Shell 脚本后,新服务器初始化大概只需要几分钟。项目标题虽然叫“linux用户管理”,但真正成熟的管理方式,一定不是今天想到就加个用户、明天报错了再改权限,而是提前把用户、组、权限、审计这四件事设计好,后面才能稳定运行。这套思路做下来,你面对的就不是一台台孤立的服务器,而是一套可以复用的用户权限体系。我自己后面扩展的方向是用户密码策略统一接入、sudoers 规则用版本管理工具管理、用户操作行为统一记录到审计平台,这些都是在用户管理这个主题上越走越深之后必然遇到的问题。
