今天想认真聊聊 Linux 的用户管理。无论你是刚装好 Ubuntu 准备折腾的桌面用户,还是天天对着生产服务器敲命令的运维,迟早都会撞上同一个问题:这台机器上的“用户”到底是怎么运作的?“Linux 的用户”这个词看起来简单,但背后牵扯到 UID、GID、用户组、家目录、shell、sudo 权限、登录日志一整套体系。我见过不少同事,用 Linux 好几年,新建用户只会照着网上一句useradd -m抄,等问起“为什么有的用户登录后没有命令提示符”“为什么新建用户后 sudo 用不了”“为什么用户删了家目录还在”,就一脸茫然。
这篇文章我打算把这套东西完整捋一遍。我不会只给你一堆命令,而是会讲到背后为什么这样设计——比如为什么用户要放在 /etc/passwd 而不是拿个数据库存起来,为什么useradd和adduser看起来像双胞胎实际上不是一回事,为什么改 UID 可能让你一堆文件“变主人”。这些内容既有面向新手的实操步骤,也有老运维踩过坑之后才会明白的细节。适合刚入门 Linux 的学生、准备面试的开发,以及所有想把用户管理摸透彻的人。
1. 用户体系为什么这么设计
1.1 多用户不是“多个账号”那么简单
很多人刚从 Windows 过来,觉得 Linux 的多用户无非就是“能多登录几个账号呗”。这个理解方向没错,但完全低估了用户体系在 Linux 里的地位。Linux 从内核层面就是一个多用户、多任务的操作系统,进程、文件、设备、网络端口,所有这些资源都挂在“某个用户”名下。系统判断“你是什么人”靠的不是屏幕前的面孔,而是你持有的用户 ID(UID)。内核只认数字,不认名字。你在/etc/passwd里把root这个名字改成admin,内核根本不在乎,它只关心你进程的 UID 是不是 0。
这就带来一个关键结论:用户机制的核心是权限隔离,而不是为了满足“登记几个账号”这种形式需求。系统想让普通用户碰不到别的用户的家目录,想让某个进程只能用 CPU 的一部分时间,想记录“谁删了这个文件”以便事后排查,都得靠 UID 的归属来做判断。文件系统里每个文件都有一个 owner UID 和一个 group GID,读、写、执行三组权限再加上特殊权限位,构成了整套访问控制。你新建一个用户,本质就是在系统里注册一个数字身份,再给这个身份安排家目录、默认 shell、附加组这些“配套装备”。
这个设计的好处是清晰、简单、性能好。验证一个文件“你能不能读”,内核做一次数字比较就结束了。坏处是对人来说不友好——所以才有passwd、ls -l里展示用户名的机制,那其实是把数字翻译成名字给你看的“装饰层”。
1.2 一个“用户”到底由哪些元素组成
拿笔把 Linux 用户体系的组成元素列出来,你会意外地发现它其实不多:
- 用户名:给人看和给程序调用的标识符,一般由小写字母、数字、下划线组成。
- UID(User ID):内核真正使用的数字标识,0 是 root,1-999 通常预留给系统账户,1000 及以上给普通用户。不同发行版划分略有差别,比如 Debian 系通常从 1000 开始创建普通用户,CentOS 也类似。
- GID(Group ID):用户主组(primary group)的数字标识。用户创建的文件默认的属组就是这个 GID 对应的组。
- 家目录(home directory):用户登录后的起始工作目录,通常叫
/home/用户名。root 的是/root。 - 登录 Shell:用户登录后启动的解释器,Ubuntu 桌面一般默认
/bin/bash,也有的系统用/usr/bin/zsh。 - 密码:密码本身不属于用户“定义”的一部分,它存在另一个文件
/etc/shadow里,而且存的是哈希值。你改了用户名或 UID,密码不受影响;但如果你删了/etc/shadow里对应行,用户就变成了“锁死”状态。
要记住的是,以上这些并不是“不可分割的整体”,你把它们拆开单独操作完全可行——你可以给一个尚未创建的用户手动创建家目录,你也可以让两个用户名共享同一个 UID(这会让系统认为它们是同一个用户,不推荐但技术上成立)。理解这点很重要,因为后面所有“诡异现象”几乎都源于“某个用户的部分信息被改了,另一部分没跟上”。
2. 用户信息到底存在哪
2.1 /etc/passwd 逐字段拆解
很多初学者第一次cat /etc/passwd会被一大串行吓到,感觉像乱码。其实每一行都是一个用户的“登记卡”,用冒号分成 7 个字段。我拿这样一行举例:
zhangsan:x:1000:1000:Zhang San:/home/zhangsan:/bin/bash字段按顺序是:用户名、密码占位符、UID、GID、注释信息、家目录、登录 Shell。
其中第二个字段现在基本都是x,只表示“密码不在这里,去 /etc/shadow 看”。这是因为历史早期密码哈希确实直接存在这个文件里,但 /etc/passwd 需要被所有程序可读(比如ls -l要把 UID 翻译成用户名,普通用户也要查),于是任何用户都能读走密码哈希,配合那个时候的弱哈希算法,离线破解非常容易。后来才把哈希挪到只有 root 能读的 /etc/shadow。这个字段保留x是兼容性设计。
注释字段(GECOS)虽然叫注释,但有些程序会读取它,比如finger命令显示的用户全名、办公电话。你给用户起中文全名放这里,表面看不出效果,但一些命令行工具会把它带出来。个人建议至少填一个能识别身份的名字,别啥都不写。
2.2 /etc/shadow 和 /etc/group 的配合
/etc/shadow 每一行对应 passwd 里一个用户,字段更多,核心包括加密后的密码哈希、上次修改密码日期、密码最短/最长有效期、过期警告天数、账户失效日期等。运维排查“某个账号怎么突然登不上”,经常要来看这个文件。常见的哈希格式像$6$salt$hash,意思是 SHA-512 算法;$y$是 yescrypt,新版本 Debian/Ubuntu 默认用它;如果看到字段是!或*,表示这个账户被锁定了。
/etc/group 存的是“组”的信息。为什么有了用户还要有组?因为权限控制需要“一批人”这个粒度。你想让项目组的五个同事都能读某个共享目录,总不能给每个用户单独设置权限,那管理员会疯掉。把他们塞进同一个组,目录的组权限一开,事情就解决了。组的四个字段是:组名、密码占位符、GID、组成员列表(这个字段只有“附加组”成员会列出来,主组通常不写,所以你看 /etc/group 会看到有些组没成员,但id 用户名却显示它在里面)。
这里顺带纠正一个常见误解:“主组”和“附加组”虽然都叫组,地位完全不同。用户创建文件的时候,文件的属组自动是主组;而附加组只是给用户“额外身份”,让人能访问其他组的资源。删了用户的主组一般不合规,但删了附加组问题不大。用户如果要添加多个组身份,要用-a -G两个参数一起用,否则很容易把用户从现有附加组里踢出来。
3. 新建用户:命令与实操细节
3.1 useradd 与 adduser:看似相同,天壤之别
新手最容易困惑的点:useradd和adduser到底啥区别?简单说:useradd是底层创建命令,参数多、功能精细,不会自动帮你生成家目录、不会设置密码、不会设置中文注释。adduser是 Debian 系(Ubuntu 也如此)提供的 Perl 脚本,它本质上在背后调用了一系列底层命令,会帮你交互式地建家目录、问密码、填全名,一步到位。
在 CentOS/RHEL 系列上,adduser其实是指向useradd的软链接,你敲 adduser 和 useradd 没有区别,都得自己加参数。所以千万别拿 Debian 的习惯去 CentOS 上裸敲adduser zhangsan,你得到的是一个连家目录都没有的账号。
我个人的偏好是:批量创建、脚本里用useradd加满参数;手动创建一两个用户用adduser更稳。但无论用哪个,都要清楚自己敲的每个参数含义。
3.2 一个标准新建命令的完整解析
以常见的生产环境建用户为例,我一般这样写:
sudo useradd -m -d /home/zhangsan -s /bin/bash -c "Zhang San" -u 1500 -g 1000 -G sudo,developers zhangsan sudo passwd zhangsan-m:自动创建家目录。不加这个,只有当你后面手动mkdir -p /home/zhangsan再chown,否则用户登录时连起始目录都不存在。-d:指定家目录路径。默认就是/home/用户名,你自己指定时要确保路径格式合理,不要带末尾斜杠。-s:指定登录 shell。如果是给运维账号,/bin/bash最舒服;如果只是个跑任务的系统账号,可以指定/usr/sbin/nologin,让它无法交互登录。-c:注释/GECOS 信息,写上真实姓名。-u:指定 UID。生产环境强烈建议手动指定,否则系统自动分配,等你后续要维护 ACL 或文件归属时会很痛苦。-g:指定主组的 GID 或组名。注意 -g 是小写,大写 -G 才是附加组,密钥难点容易写错。-G sudo,developers:把用户放进 sudo 组和 developers 组,多个组用逗号分隔。
然后单独执行sudo passwd zhangsan设置密码,系统会要求输入两次。很多人以为 useradd 之后用户就能登录,其实这时候账号密码还是空的(可能没法登录或登录后被要求立即改密),passwd 是必经步骤。
3.3 新建用户时“设置 GID”的那些坑
热搜词里有一条“linux新建用户时设置gid”,很多人就踩在这个点上。-g设置的主组,对应的组必须已存在,否则 useradd 会直接报错。如果你想“顺便新建一个同名组”,那要用-U让 useradd 自动创建同名组,或者先groupadd。我的建议是:如果这个用户要归属已有的业务组,明确指定 GID;如果用户是独立个体,CentOS 默认会创建同名主组,Ubuntu 默认也会创建同名组,这就够了。
还有一个细节:-g 1000这种写法,如果 /etc/group 存在 GID 是 1000 的组,就绑定成功;但如果你误写成某个不存在的 GID,在一些老版本上会直接报错,新版本提示也比较明确。另外,改一个已有用户的主组用usermod -g,但已存在的文件属性组不会自动跟着变,容易造成“用户明明属于组A了,但文件还是组B”的错觉。
3.4 /etc/skel:为什么新用户家目录里总有那些隐藏文件
新建用户后ls -a /home/zhangsan会看到.bashrc、.profile、.bash_logout这些文件,它们不是凭空生成的,而是从一个模板目录/etc/skel拷贝过来的。这个机制非常有用:你可以往/etc/skel里塞一些通用的.vimrc、放置公司自定义的欢迎信息.bashrc片段,以后每个新用户都会自动带上。坏消息是:已经创建的用户不会回溯应用这些模板,需要你手动 copy 过去。
我习惯在部署完一台新服务器后立刻改/etc/skel/.bashrc,把HISTSIZE调大、加上export EDITOR=vim、加上一条提示信息,这样后面所有新建账号都能少很多重复配置。但注意,模板别塞太多花活,免得每个新用户登录都会报错或行为诡异。
4. 用户修改、锁定与删除
4.1 usermod 的使用场景与边界
用户建好了,要改信息,主力工具是usermod。它相当于 useradd 的兄弟,很多参数是共用的。典型操作:
sudo usermod -L zhangsan # 锁定账号,禁止登录 sudo usermod -U zhangsan # 解锁 sudo usermod -l newname zhangsan # 修改用户名(注意:家目录和所有相关配置不会自动改) sudo usermod -d /newhome zhangsan # 改家目录路径(但内容不会自动转移) sudo usermod -aG docker zhangsan # 添加到 docker 附加组(-a 必不可少!)这里有非常多坑。修改用户名是高风险操作——你改了名字,但 UID 没变,一般情况下文件归属还认 UID,但要记住:cron 任务、systemd 服务的User=字段、sudoers 里写的名字、邮件系统、进程残留这些都还记着旧名。生产环境改名,我通常先在低峰做,改完跑一遍find / -user 旧名确认没有“孤儿文件”,再去检查关键服务的配置。
-aG这个组合拳,我特别强调:-a是 append(追加),没有它,usermod -G会用你列出的组替换用户的全部附加组。多少人因为写usermod -G docker zhangsan把用户从 sudo 组里踢出去,然后用户一脸懵“我怎么 sudo 用不了了”。安全做法是每次都带-a:usermod -aG docker zhangsan。
4.2 锁定、过期与密码策略
“禁止登录”有好几种做法,很多人混着用:
passwd -l zhangsan:锁定密码,会在 shadow 对应哈希前加!。usermod -L zhangsan:同上,效果基本一致。usermod -e 2025-12-31 zhangsan:设置账户过期日期,适合临时工或外包账号。chage -l zhangsan:查看密码与账户的老化信息。chage -M 90 zhangsan强制 90 天后必须改密码;chage -d 0 zhangsan强制下次登录先改密码。
这些操作里,我建议把chage纳入运维例行检查。安全合规审核时问“哪些账号 180 天没改过密码”,一条chage -l批量脚本就搞定。创建新账号时,也按业务的安全策略设置好-M和-e,不要什么都默认。
4.3 userdel 删除用户:不清理家目录会出大事
删除用户:
sudo userdel zhangsan # 删除用户条目,但保留家目录和邮件 sudo userdel -r zhangsan # 连同家目录、邮件池一起删除问题出在生产环境:很多管理员不敢用-r,怕删错数据,于是只执行不带 -r 的 userdel,结果用户没了,家目录和一堆文件留在原地,占磁盘不说,还容易在新项目扫描时发现“一个不存在的用户拥有 30GB 数据”。这种残留也会干扰后续新建同名的用户——新用户 UID 重新分配后,旧文件的属主显示成新用户名,看起来就像“新用户突然有一堆不明文件”。
我建议删除前先做好两件事:第一,find / -user 目标用户名把归属确认一遍;第二,归档转移重要数据而不是直接删。这样之后你可以放心用-r。如果只想“留数据但去账号”,那删除后把家目录 chown 给接手人,例如chown -R newowner:newgroup /home/zhangsan。
5. 权限、组与 sudo 实践
5.1 用户与组权限的配合套路
用户本身就是“最小权限单元”,组是“批量授权单元”。最常见的实践是建业务组,然后把相关用户加进组里:
sudo groupadd developers sudo usermod -aG developers zhangsan sudo mkdir -p /srv/project sudo chown root:developers /srv/project sudo chmod 2770 /srv/project这里2770里的2是 setgid 位,作用很妙:目录被设置了 setgid 之后,任何用户在目录里新建文件,文件的属组自动继承目录的组(developers),而不是用户自己的主组。这样整个团队的文件都能共享写权限,不会因为“张三的主组是张三”而导致同事改不了文件。生产环境共享协作目录我基本都会加 setgid。
5.2 sudo 权限的设计与踩坑
新用户默认没有 sudo 权限。Debian 系把有 sudo 权限的人加进sudo组,CentOS 系则是wheel组。你可以:
sudo usermod -aG sudo zhangsan # Debian/Ubuntu sudo usermod -aG wheel zhangsan # CentOS/RHEL更精细的做法是编辑/etc/sudoers.d/下的文件,而不是直接改/etc/sudoers。比如给 zhangsan 只允许重启服务:
zhangsan ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx表示 zhangsan 可以在所有主机上,以任何用户身份,免密执行重启 nginx 这一个命令。注意一行命令路径尽量写绝对路径,防止黑客用同名的假命令做 PATH 劫持。编辑 sudoers 全程要带visudo,它会做语法检查;我见过直接改文件写错语法导致整个 sudo 系统瘫痪,所有用户都无法提权,只能重启进单用户模式去修。
5.3 为什么“用户文件夹名称”不能随便改
热搜词里那条“如何修改用户文件夹名称”,其实问的是家目录。很多人想改/home/zhangsan为/home/zs,然后直接用mv,结果登录就崩。因为系统里有很多地方记录着旧家目录路径:/etc/passwd 的字段、systemd 用户会话服务、桌面环境的 XDG 目录、缓存路径等。
正确做法是用 usermod 配合移动:
sudo usermod -d /home/zs -m zhangsan-m会让 usermod 同时把旧家目录内容搬过去,并同步更新 /etc/passwd 里的路径。这是相对稳妥的办法,但也不能保证 100% 无感——如果该用户有正在运行的进程或打开的会话,最好先退出登录再操作。改完建议重启一次用户的登录会话。
6. 常见问题排查与运维实战
6.1 如何从 auth.log 定位“谁登录过”
热搜词里有/var/log/auth.log溯源登录成功的需求,这是 Ubuntu/Debian 系的重要日志文件。做安全审计时,先查登录成功记录:
sudo cat /var/log/auth.log | grep "Accepted publickey" sudo cat /var/log/auth.log | grep "Accepted password" sudo cat /var/log/auth.log | grep "Failed password"Reporter 若想按“用户 mage”过滤,直接:
sudo grep "mage" /var/log/auth.log | grep "session opened"日志里能看出登录方式(SSH 公钥还是密码)、来源 IP、端口、验证时间,以及后续 session 打开/关闭。整改建议也只有一条:SSH 能上公钥就公钥,禁用密码登录,常用用户名别用 admin、test、mage 这种容易被猜测的名字。
CentOS/Stream 系对应的日志在/var/log/secure,排查思路一样。
6.2 用户家目录里出现“未知项目目录”
有一种情况很常见:新用户登录后,ls看到家目录里冒出一个自己没见过、名字却是项目名的目录,或者反过来,某些软件检测到“应用安装目录下存在用户项目目录”。很多用户第一反应是“是不是被入侵了”。其实大概率是历史遗留:之前某个用户的家目录在这里,或者某次安装过程以该用户身份创建了目录,后来用户删了,目录留了下来。排查办法:
ls -la /home/用户名 stat /home/用户名/神秘目录 find /home/用户名 -maxdepth 2 -mtime -30stat看创建时间、属主、属组,find按时间过滤最近改动。确认无关后直接删除或者归档。如果目录属主显示的 UID 没有对应的用户名,那说明这个 UID 对应的用户已被删除,这同上面第 4.3 节讲的残留场景是同一条链路。
6.3 用户权限不足:拒绝访问内存文件
热搜词里还有一条“用户拒绝访问内存文件权限怎么办”。这是典型的安全机制,比如/proc、/sys下有大量虚拟文件,普通用户想读里面某些进程信息或者设备状态,会被内核拒绝。很多应用提示“检测到用户拒绝访问内存文件权限”是因为它尝试读取/proc/self/pagemap或某个性能计数器,而内核基于ptrace_scope或安全模块做了限制。
正常的排查路径:
- 确认是哪个文件权限不足:用
ls -la看属主、权限位。 - 如果是普通数据文件,
chown或chmod调整归属。 - 如果是
/proc相关虚拟文件,不要尝试 chmod 强行改内核接口的权限,那是无效甚至危险的,应该去查找该软件需要的实际权限来源,比如运行时加CAP_SYS_ADMIN或者调整/proc/sys/kernel/yama/ptrace_scope。 - 实在排查不清,看软件日志里具体报错的是哪条 syscall,再对症下药。
这类问题的核心原则是:权限拒绝是系统在保护你,先搞清楚为什么拒绝,再决定是否放宽。
6.4 后台运行指令不因退出而终止
热搜词有“linux 让后台运行指令 不因界面退出而退出”,这看着跟用户没关系,但深究起来和“用户会话”的概念强绑定。当你 SSH 登录执行一个进程,它就是“你的会话子进程”,一旦你退出,系统会发送 HUP 信号把它挂断。这就是“nohup”存在的意义:
nohup ./myserver.log &&把命令放到后台,nohup 忽略 HUP 信号。更现代的方式是:
sudo systemd-run --unit=myservice --property=User=zhangsan ./myserver这样会把你的程序托管成 systemd 用户服务或系统服务,独立于你的登录会话,用户可以退出,程序照跑。但要注意,如果你用普通用户的 systemd 用户实例,有的发行版需要开启 lingering:
sudo loginctl enable-linger zhangsan这行命令的意思正是:让 zhangsan 的 user session 在他退出登录后仍然保留,从而让它的 systemd 用户服务得以继续运行。这里你能清楚看到“用户会话”生命周期对进程的影响,这也是运维必踩的一个基础概念。
6.5 几台机器常见故障速查
| 现象 | 可能原因 | 处理建议 |
|---|---|---|
| 新用户无法登录 | 没执行 passwd 或账号锁定 | 执行sudo passwd 用户名 |
| 登录后没有家目录提示 | 家目录没创建或权限不对 | mkdir -p家目录然后chown -R |
| sudo 命令报“不在 sudoers file 中” | 用户不在 sudo 组,或 sudoers 里没写 | usermod -aG sudo或 visudo 加条目 |
| 用户删了,磁盘没释放 | userdel 未加 -r | find / -nouser找出来归档/清理 |
| 改完用户名 SSH 登录失败 | 家目录/配置未同步 | usermod -l后检查 passwd、家目录、旧引用 |
| 文件属主显示数字 UID | 该 UID 在 /etc/passwd 中无对应用户 | 手动创建 UID 或 chown 到现有用户 |
| 用户能登录但无法操作 GUI | 未加入 video/input 等设备组 | usermod -aG video,audio,input 用户名 |
| 用户目录权限拒绝 | 家目录权限不足或 ACL 限制 | chmod 700或设置 ACL |
| 进程退出后自动被杀 | 未脱离用户会话 | nohup / setsid / systemd-run |
6.6 给新手的用户管理自检清单
最后给一个自查路线,照着做一遍基本能覆盖“用户管理”这条线:
id 用户名:看 UID、GID、所属组是否合理。finger 用户名(若装了)或grep 用户名 /etc/passwd:确认家目录、shell、注释字段。ls -ld /home/用户名:确认家目录存在且权限正常(通常是 755 或 700)。sudo -l -U 用户名:看该用户有哪些 sudo 权限。lastlog | grep 用户名:看最近登录记录。chage -l 用户名:看密码策略与过期时间。
每一条都跑一遍,你对某个账号的状态就有全景认知。等这些基本命令变成肌肉记忆,你再去碰那些看起来很玄的“用户权限导致应用启动失败”“用户目录权限不足”的故障,就能沿着“文件归属是不是这个用户->用户能否访问路径每一级->用户会话状态是否正常”这条线快速定位。
我个人在实操里最深的体会有两条。第一,Linux 的用户管理实际上是在管理数字、映射和引用——你的键盘输入最终变成对 UID/GID 的操作,系统里到处留着对这个身份的引用(文件、进程、服务配置、定时任务),用户删除或改名时,要瞪大眼睛把所有引用一起处理。第二,生产环境永远不要在没确认前执行userdel -r或chown -R到错误的目标,这类命令不可逆,一旦批量跑错,恢复成本可能比重建一台机器还高。把这个谨慎刻进习惯里,你的用户管理就不会出大乱子。