之前在准备 Linux 运维和系统管理相关的面试内容时,用户管理这一块几乎每次都会被问到,尤其是/etc/passwd、/etc/shadow、/etc/group这几个文件。很多刚入行的同学能背出useradd、passwd命令,但一被问到底层改了什么文件、每个字段代表什么含义,就答不上来了。实际上,Linux 的所有账户操作最终都会落到这些配置文件上,理解了文件结构,命令只是顺带的事。
本文将围绕 Linux 用户管理的核心配置文件展开,逐一拆解/etc/passwd、/etc/shadow、/etc/group、/etc/gshadow的文件格式与字段含义,再把/etc/login.defs、/etc/default/useradd、/etc/skel这几个关联配置讲清楚。文章末尾会整理常见的面试题和排错思路,帮助你在面试和实际运维中都能快速找到思路。
1. 为什么要重点掌握用户相关配置文件
Linux 是一个多用户、多任务的操作系统,用户管理是所有系统管理工作的基础。用户能够登录系统、访问文件、执行命令,靠的并不是“记住一个名字”,而是系统在底层去检查一组配置文件。
先思考一个问题:当你在终端执行useradd zhangsan时,系统到底做了什么?
一条命令执行后,系统实际上是依次修改了多个文件:
- 向
/etc/passwd追加了一行用户基本信息。 - 向
/etc/shadow追加了一行密码信息。 - 如果指定了用户组,还要更新
/etc/group文件。 - 同时从
/etc/skel目录复制默认的配置文件到新用户家目录。 - 最后创建
/home/zhangsan目录并设置权限。
也就是说,用户管理的本质,就是对这一组配置文件进行读写。面试中问配置文件,并不是为了考背诵,而是考察你是否理解系统账户体系的运作方式。
与此同时,这些文件也是排查用户问题的重要入口。比如用户无法登录、密码过期、找不到家目录、权限异常、无法切换用户等,这些问题最终都要回溯到配置文件中的字段值。掌握了字段含义,就相当于拿到了排查故障的第一手工具。
下图可以帮你理解用户管理配置文件之间的关系:
用户管理相关配置文件 ├── /etc/passwd 用户账户基本信息 ├── /etc/shadow 用户密码与过期策略 ├── /etc/group 用户组基本信息 ├── /etc/gshadow 用户组密码与组管理员 ├── /etc/login.defs 全局用户默认属性 ├── /etc/default/useradd useradd 命令默认配置 └── /etc/skel 用户家目录模板文件下面我们从最核心的四个文件开始逐步拆解。
2. /etc/passwd:用户账户信息主文件
2.1 文件作用
/etc/passwd是 Linux 系统中存储用户账户信息的文本文件。系统每次用户登录时,都会读取这个文件来获取用户名、UID、家目录和登录 Shell 等信息。
需要注意的是,/etc/passwd对所有用户都是可读的,因为它包含的是非敏感信息,比如用户名和家目录路径。它并不直接保存密码,真正的密码密文存放在/etc/shadow中,这也是为什么passwd文件中密码字段通常是一个x。
2.2 文件格式与字段说明
/etc/passwd中每行代表一个用户账户,格式如下:
用户名:密码占位符:UID:GID:注释信息:家目录:登录Shell下面用一个实际例子来说明:
zhangsan:x:1000:1000:张三:/home/zhangsan:/bin/bash| 字段位置 | 字段名 | 示例值 | 含义说明 |
|---|---|---|---|
| 1 | 用户名 | zhangsan | 登录系统时使用的账户名,不能包含冒号 |
| 2 | 密码占位符 | x | 表示真实密码存储在 /etc/shadow 中 |
| 3 | UID | 1000 | 用户 ID,系统内核通过 UID 识别用户 |
| 4 | GID | 1000 | 用户主组 ID,对应 /etc/group 中的组 |
| 5 | 注释信息 | 张三 | 通常为用户全名、联系方式等描述,可以为空 |
| 6 | 家目录 | /home/zhangsan | 用户登录后的默认工作目录 |
| 7 | 登录 Shell | /bin/bash | 用户登录后启动的 Shell 程序 |
看到这里你可能会问,为什么密码字段不直接写密文?早期 Unix 系统确实直接把密码密文放在/etc/passwd的第二个字段中。但后来人们发现这个文件需要被所有用户读取(很多程序需要查询用户名和 UID),这样一来密码密文就暴露给了所有人,任何人都可以用暴力破解工具去尝试。于是系统改成了 shadow 机制,把密码密文转移到只有 root 用户可读的/etc/shadow文件中,而/etc/passwd的第二个字段统一用x占位。
2.3 UID 与 GID 的分配规则
在 CentOS、Ubuntu 等发行版中,UID 的分配是有策略的:
- 0:root 用户,超级用户。
- 1-999:系统用户,例如
bin、daemon、sshd、nginx等。这些用户通常用于运行后台服务,不需要登录系统。 - 1000-60000:普通用户,通过
useradd创建的用户默认从 1000 开始分配。
GID 的规则与 UID 类似,不单独划分。
UID 范围: 0 → root 超级用户 1-999 → 系统服务账户 1000+ → 普通用户在面试中,如果被问到“如何查一个用户的 UID”,可以直接使用:
id zhangsan输出示例:
uid=1000(zhangsan) gid=1000(zhangsan) groups=1000(zhangsan),10(wheel)如果想直接查看/etc/passwd中某一行的内容:
grep zhangsan /etc/passwd3. /etc/shadow:用户密码与过期策略文件
3.1 文件作用
/etc/shadow是保存用户密码密文及密码策略的文件。它只允许 root 用户和具有必要权限的程序读取,普通用户无法查看,这样大大提高了密码的安全性。
这个文件解决的不仅是“密码隐藏”的问题,还引入了密码过期、密码最小修改间隔、账号失效等字段,让系统管理员可以精细化控制账号生命周期。
3.2 文件格式与字段说明
/etc/shadow中每行对应一个用户,格式如下:
用户名:加密密码:最后一次修改时间:最小修改间隔:最大有效天数:提前警告天数:过期宽限天数:账号失效日期:保留字段实际示例:
zhangsan:$6$abc123$xxxxxxxx:20000:0:99999:7:0:19799:| 字段位置 | 字段名 | 示例值 | 含义说明 |
|---|---|---|---|
| 1 | 用户名 | zhangsan | 与 /etc/passwd 中的用户名对应 |
| 2 | 加密密码 | $6$... | 密码密文,!或!!表示锁定或无密码 |
| 3 | 最后一次修改时间 | 20000 | 从 1970-01-01 到最近一次改密码的天数 |
| 4 | 最小修改间隔 | 0 | 距上次修改至少多少天后才能再次修改 |
| 5 | 最大有效天数 | 99999 | 密码最长使用天数,超过后必须修改 |
| 6 | 提前警告天数 | 7 | 密码过期前多少天开始提醒用户 |
| 7 | 过期宽限天数 | 0 | 密码过期后仍允许登录的天数 |
| 8 | 账号失效日期 | 19799 | 从 1970-01-01 起算的账号失效日期 |
| 9 | 保留字段 | 空 | 保留未使用 |
第三段时间“最后一次修改时间”通常新手看不懂,它不是一个日期格式,而是天数。可以通过下面命令换算成可读日期:
# 例如 shadow 中第三个字段是 20000 date -d "1970-01-01 20000 days" +"%Y-%m-%d"关于密码加密算法,$6$表示 SHA-512,$5$表示 SHA-256,$1$表示 MD5,$y$表示 yescrypt(部分新版发行版)。看到以$开头的密文时,可以通过第一个分隔段判断算法类型。
3.3 密码锁定状态
如果/etc/shadow中密码字段以!或!!开头,表示该用户密码被锁定,无法登录。例如:
zhangsan:!!$6$abc123$xxxxxxxx:20000:0:99999:7:0:19799:这里!!是 passwd -l 锁定操作留下的标记。解锁操作则使用:
passwd -u zhangsan还有种情况是新用户刚创建时,密码字段就是!!,表示尚未设置密码。此时必须用passwd zhangsan设置密码后才能登录。
4. /etc/group 与 /etc/gshadow:用户组信息
4.1 /etc/group 基本格式
Linux 的权限模型不仅针对用户,也针对用户组。用户组方便了权限的批量分配,比如把多个开发人员加入同一个组,然后设置该组对某个目录有读写权限。
/etc/group中每行代表一个组:
组名:密码占位符:GID:组成员列表示例:
devteam:x:1001:zhangsan,lisi,wangwu| 字段位置 | 字段名 | 示例值 | 含义说明 |
|---|---|---|---|
| 1 | 组名 | devteam | 组的名称 |
| 2 | 组密码占位符 | x | 真实组密码存放在 /etc/gshadow |
| 3 | GID | 1001 | 组的唯一 ID |
| 4 | 组成员 | zhangsan,lisi | 逗号分隔的组成员列表 |
注意区分“主组”和“附加组”:
- 主组:用户在
/etc/passwd中第 4 字段指定的 GID,创建文件时默认属组。 - 附加组:用户额外加入的组,用于扩展权限。
查看用户所在所有组可以使用:
groups zhangsan4.2 /etc/gshadow 基本格式
/etc/gshadow与/etc/shadow类似,存储用户组的密码和组管理员信息:
组名:加密组密码:组管理员:组成员示例:
devteam:!:zhangsan:zhangsan,lisi,wangwu字段含义如下:
- 组名:与
/etc/group第一字段一致。 - 加密组密码:如果为
!表示没有组密码或组密码被锁定。 - 组管理员:有权限修改组密码和组成员的用户列表,逗号分隔。
- 组成员:属于该组的用户列表。
组密码在实际使用中频率并不高。一般场景下,用户加入附加组是通过 root 用usermod -G完成,而不是通过组密码。
5. 用户管理的辅助配置文件
5.1 /etc/login.defs:全局密码策略与 UID 范围
/etc/login.defs定义了创建用户和密码策略时的一组默认值。它被useradd、passwd、chage等命令读取。
常见配置项如下:
配置示例:/etc/login.defs 关键片段 PASS_MAX_DAYS 99999 PASS_MIN_DAYS 0 PASS_MIN_LEN 5 PASS_WARN_AGE 7 UID_MIN 1000 UID_MAX 60000 SYS_UID_MIN 201 SYS_UID_MAX 999 GID_MIN 1000 GID_MAX 60000 CREATE_HOME yes UMASK 077 USERGROUPS_ENAB yes这些配置项的含义:
PASS_MAX_DAYS:密码最大有效天数,超过后强制修改密码。PASS_MIN_DAYS:两次修改密码之间的最小间隔天数。PASS_MIN_LEN:密码最小长度。PASS_WARN_AGE:密码过期前警告天数。UID_MIN、UID_MAX:普通用户的 UID 范围。SYS_UID_MIN、SYS_UID_MAX:系统用户的 UID 范围。CREATE_HOME:是否默认创建家目录。UMASK:新用户家目录和文件权限掩码,077表示家目录权限为700。USERGROUPS_ENAB:是否在创建用户时自动创建同名主组。
需要注意的是,/etc/login.defs中的配置只是默认值,如果useradd命令显式指定了参数,则命令参数优先于配置文件。
5.2 /etc/default/useradd:useradd 命令默认值
/etc/default/useradd主要被useradd命令读取,用于确定新用户的默认家目录路径、默认登录 Shell、默认主组等。
典型内容:
配置示例:/etc/default/useradd GROUP=100 HOME=/home INACTIVE=-1 EXPIRE= SHELL=/bin/bash SKEL=/etc/skel CREATE_MAIL_SPOOL=yes字段含义:
GROUP=100:默认主组 GID,如果/etc/login.defs设置了USERGROUPS_ENAB yes,通常会自动创建同名组,这里不一定会生效。HOME=/home:用户家目录的父目录。INACTIVE=-1:密码过期后账号宽限天数,-1表示不启用该策略。EXPIRE=:账号失效日期,空表示不设置。SHELL=/bin/bash:默认登录 Shell。SKEL=/etc/skel:创建家目录时的模板目录。CREATE_MAIL_SPOOL=yes:是否创建用户对应的邮件池文件。
5.3 /etc/skel:用户模板目录
/etc/skel是一个模板目录,里面存放着新用户家目录的默认文件。当你执行useradd创建用户时,系统会自动把/etc/skel中的所有文件(包括隐藏文件)复制到新用户的家目录中。
常见的模板文件包括:
.bashrc:用户交互式 Shell 配置。.bash_profile:登录 Shell 配置文件。.bash_logout:退出登录时执行的脚本。- 其他
.vimrc、.zshrc等文件可以根据需要自行添加。
比如你想让所有新用户默认看到一段欢迎信息,可以这样操作:
echo "Welcome to Linux Server" > /etc/skel/welcome.txt之后再创建的新用户,家目录下就会自动多出welcome.txt。已经存在的用户不会自动获得该文件,需要手动复制。
6. 实战:通过文件变化理解用户管理全过程
理论知识说完之后,我们进入一个实操环节。通过实际操作来观察创建用户时文件的变化,把所有知识点串起来。
6.1 创建用户并观察文件变化
在 root 权限下执行:
useradd -m testuser-m参数表示创建用户的同时创建家目录。执行后查看相关配置文件:
grep testuser /etc/passwd grep testuser /etc/shadow grep testuser /etc/group第一次执行时,由于还没有设置密码,你会看到类似输出:
testuser:x:1002:1002::/home/testuser:/bin/bash testuser:!!:20015:0:99999:7:0:19799: testuser:x:1002:逐行解释:
/etc/passwd中多了一行,UID 是 1002,GID 是 1002,家目录是/home/testuser,登录 Shell 是/bin/bash。/etc/shadow中密码字段是!!,表示用户尚未设置密码,不能登录。/etc/group中新增一个组testuser,GID 为 1002。这是因为默认配置USERGROUPS_ENAB yes,系统自动创建了与用户名同名的组。
再查看家目录内容:
ls -la /home/testuser你会看到从/etc/skel复制过来的隐藏文件,例如.bashrc、.bash_profile、.bash_logout。
6.2 设置密码并观察 shadow 变化
给用户设置密码:
passwd testuser设置完成后再次查看 shadow 文件:
grep testuser /etc/shadow此时密码字段从!!变成了长串密文,类似:
testuser:$6$8gLxR4zI$fL0...:20015:0:99999:7:0:19799:说明密码已经生效。此时可以用su切换用户验证:
su - testuser6.3 修改用户属性并观察文件变化
把 testuser 的登录 Shell 改为/sbin/nologin:
usermod -s /sbin/nologin testuser再次查看:
grep testuser /etc/passwd输出中的最后一个字段会从/bin/bash变成/sbin/nologin。设置为/sbin/nologin后,该用户无法通过 SSH 或终端直接登录系统,但可以作为服务账户运行程序。
把用户加入附加组 wheel:
usermod -aG wheel testuser查看用户能力:
groups testuser id testuser输出示例:
testuser : testuser wheel uid=1002(testuser) gid=1002(testuser) groups=1002(testuser),10(wheel)这里的10(wheel)就是附加组,testuser是主组。
6.4 设置密码过期策略
查看用户密码策略:
chage -l testuser输出示例:
最近一次密码修改时间 :2月 04, 2025 密码过期时间 :从不 密码失效时间 :从不 帐户过期时间 :从不 两次改变密码之间相隔的最小天数 :0 两次改变密码之间相隔的最大天数 :99999 在密码过期之前警告的天数 :7设置密码 90 天后过期,提前 7 天警告:
chage -M 90 -W 7 testuser再次查看 shadow 文件对应行:
testuser:$6$...:20015:0:90:7:0:19799:字段变化非常直观:最大有效天数从 99999 变成了 90,警告天数从 7 保持为 7。
7. 高频面试题与回答思路
这一部分整理一些面试场景中常见的问题。面试官不一定等你背答案,更想看你是否理解原因和场景。
7.1 为什么 /etc/passwd 中的密码字段是 x 而不是密文?
这是最基础的问题,回答思路有三点:
/etc/passwd需要被所有用户读取,因为很多程序需要通过它获取用户名、UID 和家目录信息。- 如果将密码密文存放在其中,相当于把密文暴露给所有用户,增加被暴力破解的风险。
- 因此系统采用 shadow 机制,将密文转移到仅 root 可读的
/etc/shadow文件中,/etc/passwd中的x只是占位符,表示真实密码在 shadow 中。
还可以追问一句:/etc/shadow的权限是怎样的?一般答案是-rw-------,只有 root 用户可读写。
7.2 UID 为 0 的用户为什么危险?
UID 为 0 是超级用户的标志,系统内核判断权限时只看 UID。如果一个普通用户被改成 UID 0,那它就会拥有 root 权限。面试中如果被问到检查系统是否有异常 uid 为 0 的用户,可以执行:
awk -F: '$3==0{print $1}' /etc/passwd正常情况下输出只有root。如果出现其他用户名,说明存在安全隐患。
7.3 创建用户时 system user 和普通用户有什么区别?
使用useradd -r可以创建系统用户。主要区别:
- 系统用户 UID 在
/etc/login.defs的SYS_UID_MIN到SYS_UID_MAX范围内,普通用户 UID 在UID_MIN到UID_MAX之间。 - 系统用户通常没有家目录,或家目录不常用。
- 系统用户默认 Shell 通常是
/sbin/nologin,不允许登录。 - 系统用户用于运行服务进程,例如 nginx、mysql 等。
7.4 如何让一个用户不能登录系统但又保留账户?
有三种常见做法:
- 将用户 Shell 改为
/sbin/nologin:只影响登录,不影响该用户运行已启动的服务。 - 在
/etc/shadow密码字段前加!锁定用户:用户完全无法通过密码认证。 - 使用
usermod --expiredate 1设置账号过期,使账号在过期日之后失效。
一般推荐第一种,因为它保留了服务运行能力,同时禁止交互式登录。
7.5 useradd 和 adduser 有什么区别?
在 Debian/Ubuntu 系列系统中,adduser是一个 Perl 脚本,封装了useradd并增加了交互式流程,如设置密码、填写用户信息。在 RHEL/CentOS 系列系统中,useradd是底层命令,adduser 可能只是 useradd 的链接或并不存在。面试时可以先说清这一点,再说明实际项目更倾向于使用带参数的命令或脚本批量创建。
8. 常见问题与排错思路
8.1 用户无法登录
现象:输入密码后认证失败,或者账号被锁定。
排查顺序:
# 1. 查看用户是否存在 id username # 2. 查看 /etc/shadow 中密码字段是否以 ! 开头 grep username /etc/shadow # 3. 查看用户 Shell 是否为 nologin grep username /etc/passwd # 4. 查看账号是否过期 chage -l username对应处理方式:
- 密码字段为
!!:设置密码passwd username。 - 密码已过期:使用
chage -M 90 username或强制重新设置密码。 - Shell 为
/sbin/nologin:改用usermod -s /bin/bash username。 - 账号过期:使用
usermod -e "" username取消过期日期。
8.2 用户已存在但家目录丢失
现象:登录后进入/,提示无法切换目录。
排查与恢复:
# 查看家目录路径 grep username /etc/passwd # 创建家目录并复制模板 mkdir /home/username cp -r /etc/skel/. /home/username/ # 修改属主属组和权限 chown -R username:username /home/username chmod 700 /home/username8.3 删除用户后 UID 被复用
如果你强制删除了用户,但没有删除 UID 对应的文件,之后创建新用户时,系统可能会复用这个 UID,导致新用户继承原来用户文件的属主关系。这在实际生产环境中有安全隐患。
安全删除流程:
# 1. 锁定用户 passwd -l username # 2. 查看用户相关文件 find / -uid 1005 2>/dev/null # 3. 确认后删除用户及家目录 userdel -r username尽量避免先删用户再发现遗留文件,因为 UID 无法快速找回归属。
8.4 普通用户无法切换到 root
现象:su -提示认证失败。
原因通常是/etc/pam.d/su或/etc/pam.d/su-l中配置了wheel组限制,只有 wheel 组成员可以提权到 root。解决方法:
# 将用户加入 wheel 组 usermod -aG wheel username也可以检查 Pam 配置,但一般推荐将管理员账号加入 wheel 组而不是直接改 Pam 规则。
9. 最佳实践与工程建议
9.1 不要手动编辑 shadow 文件设置密码
很多新手在用passwd修改密码失败后会尝试直接编辑/etc/shadow写入密文,这是比较危险的操作。如果密文格式错误或者权限不对,会导致用户无法登录。正确做法是使用passwd命令,或者通过脚本批量执行chpasswd。
批量创建用户并设置密码的示例:
for user in dev01 dev02 dev03; do useradd -m -s /bin/bash "$user" echo "$user:Init@123" | chpasswd passwd -e "$user" done其中passwd -e会让用户下次登录时强制修改密码。
9.2 修改配置文件前先备份
在修改/etc/passwd、/etc/shadow、/etc/group这类系统关键文件前,建议先备份。很多发行版在useradd、usermod等命令内部已经通过 PAM 和 shadow 机制保证原子性,但如果你需要手动改文件,备份就是最基本的保障:
cp /etc/passwd /etc/passwd.bak.$(date +%F) cp /etc/shadow /etc/shadow.bak.$(date +%F) cp /etc/group /etc/group.bak.$(date +%F)9.3 合理规划 UID 范围
生产环境中,建议为不同业务或不同应用系统划分 UID 范围,比如运维账号1000-1999,应用账号2000-2999,服务账号使用系统用户范围。这样可以减少 UID 冲突,也方便审计。创建用户时显式指定 UID:
useradd -m -u 2501 -s /bin/bash appuser9.4 定期审计用户账户
定期检查系统中是否存在异常 UID 为 0 的用户、空密码用户、近期不活跃的用户:
# 查找 UID 为 0 的用户 awk -F: '$3==0{print $1}' /etc/passwd # 查找空密码用户 awk -F: '($2==""){print $1}' /etc/shadow # 查找密码永不过期的用户 awk -F: '$5==99999{print $1}' /etc/shadow将这些命令写入定时任务或自动化巡检脚本中,是运维工作中比较常见的安全手段。
9.5 理解 PAM 与配置文件的边界
配置文件定义了用户和密码的数据,但真正的认证逻辑由 PAM(可插拔认证模块)控制。比如你设置了/etc/login.defs中的PASS_MIN_LEN,但程序如果绕过了 PAM 检查,这个最小长度未必会强制生效。理解这个边界,能帮助你在排查认证类问题时看得更准。
10. 总结与下一步学习路径
掌握 Linux 用户管理配置文件,本质上是理解了系统账户体系的底层数据结构。通过这篇文章,你应该已经能够做到:
- 说出
/etc/passwd、/etc/shadow、/etc/group、/etc/gshadow四个文件的字段含义。 - 解释为什么密码字段存放位置从
/etc/passwd迁移到/etc/shadow。 - 使用
useradd、usermod、passwd、chage命令后,知道底层哪些文件发生了变化。 - 快速排查用户无法登录、账号过期、家目录丢失等常见问题。
下一步可以继续学习的内容包括:用户切换命令(su、sudo)的配置与区别、PAM 认证机制、文件权限体系中 ACL 和特殊权限位(如 SUID、SGID)的应用。如果你在实际配置中遇到某个字段不太确定,建议多用man shadow、man passwd、man login.defs查阅对应手册,这些资料比任何博客都更权威。
最后还是那句话:Linux 用户管理命令固然重要,但配置文件才是真正的幕后逻辑。多动手创建几个用户,对照文件变化去看,很快就能把这些知识点内化。如果这篇教程对你有帮助,可以收藏备用,后续遇到用户管理相关面试题时再翻一翻,思路会清晰很多。