passwd 命令详解与参数实测(Ubuntu 22.04)
passwd 逐参数实测详解:/etc/shadow 九字段与 yescrypt 哈希、-S 状态七字段、root 与自助两种交互式改密全流程、-l/-u 锁定解锁(su 登录验证)、-d 删除密码、-e 强制过期、-n/-x/-w/-i 有效期策略对照、-k/-q/-r/-R、-aS 全账号巡检与 chpasswd 非交互替代,全部回显在 Ubuntu 22.04(shadow 4.8.1)实测通过。
passwd 命令详解与参数实测(Ubuntu 22.04)
目标:全面掌握 passwd 的每一个常用参数——
-S状态七字段解读、root 与自助两种交互式改密全流程、-l/-u锁定解锁(含登录验证)、-d删除密码、-e强制过期、-n/-x/-w/-i有效期策略、-k/-q/-r/-R、-a全账号巡检与chpasswd非交互替代,全部命令与回显已在 Ubuntu 22.04(shadow 4.8.1)实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- passwd 版本:shadow-utils
1:4.8.1-2ubuntu2.2(dpkg 实测,见 2.3;该版本的 passwd 不支持--version/-V选项,为实测确认的事实) - 测试账号:
u4c1(uid=1006)、u4c2(uid=1007)、u4c3(uid=1010),初始口令统一为演示口令q1w2e3r4 - 权限视角:root 可管理任意账号;普通用户仅能改自己的密码(3.13 实测边界)
- 本环境为最小化安装,未启用 pam_pwquality 口令质量模块,弱口令检查行为与完整版系统存在差异(3.2 中如实呈现)
二、命令概览
2.1 语法与测试数据
passwd 属于 shadow-utils 工具集,用于修改与查看账户口令数据。root 可以指定任意账号(改密、锁定、设策略),普通用户不带参数执行时修改的是自己的密码(需先验证当前密码)。
语法:passwd [选项] [LOGIN]
💡 技术拓展:与口令相关的两个核心数据文件——
文件 权限 内容 谁可读 /etc/passwd 644 root:root 账号基本信息(不含口令哈希) 所有人 /etc/shadow 640 root:shadow 口令哈希与有效期策略 仅 root(shadow 组可读) 早期 Unix 把哈希放在 /etc/passwd 第二字段,任何人可读即存在离线破解风险;现代发行版全部把哈希挪进仅 root 可读的 /etc/shadow(shadow suite 因此得名)。实测两个文件的权限见 3.1。
测试账号初始状态(root 下验证):
$ id u4c1
uid=1006(u4c1) gid=1009(u4c1) groups=1009(u4c1),27(sudo)
$ id u4c2
uid=1007(u4c2) gid=1010(u4c2) groups=1010(u4c2),27(sudo)
$ id u4c3
uid=1010(u4c3) gid=1013(u4c3) groups=1013(u4c3)
2.2 --help 全量输出
$ passwd --help
Usage: passwd [options] [LOGIN]
Options:
-a, --all report password status on all accounts
-d, --delete delete the password for the named account
-e, --expire force expire the password for the named account
-h, --help display this help message and exit
-k, --keep-tokens change password only if expired
-i, --inactive INACTIVE set password inactive after expiration
to INACTIVE
-l, --lock lock the password of the named account
-n, --mindays MIN_DAYS set minimum number of days before password
change to MIN_DAYS
-q, --quiet quiet mode
-r, --repository REPOSITORY change password in REPOSITORY repository
-R, --root CHROOT_DIR directory to chroot into
-S, --status report password status on the named account
-u, --unlock unlock the password of the named account
-w, --warndays WARN_DAYS set expiration warning days to WARN_DAYS
-x, --maxdays MAX_DAYS set maximum number of days before password
change to MAX_DAYS
2.3 版本信息
该版本 passwd 不支持 --version(实测直接报错并回显用法):
$ passwd --version
passwd: unrecognized option '--version'
Usage: passwd [options] [LOGIN]
Options:
-a, --all report password status on all accounts
-d, --delete delete the password for the named account
-e, --expire force expire the password for the named account
-h, --help display this help message and exit
-k, --keep-tokens change password only if expired
-i, --inactive INACTIVE set password inactive after expiration
to INACTIVE
-l, --lock lock the password of the named account
-n, --mindays MIN_DAYS set minimum number of days before password
change to MIN_DAYS
-q, --quiet quiet mode
-r, --repository REPOSITORY change password in REPOSITORY repository
-R, --root CHROOT_DIR directory to chroot into
-S, --status report password status on the named account
-u, --unlock unlock the password of the named account
-w, --warndays WARN_DAYS set expiration warning days to WARN_DAYS
-x, --maxdays MAX_DAYS set maximum number of days before password
change to MAX_DAYS
-V 同样不受支持(passwd: invalid option -- 'V')。版本信息以 deb 包为准:
$ dpkg -l passwd | tail -1
ii passwd 1:4.8.1-2ubuntu2.2 amd64 change and administer password and group data
💡 说明:shadow-utils 各工具的
-V/--version支持不一致(如chpasswd --version可用),遇到invalid option时用dpkg -l 包名取版本最可靠。
2.4 密码存储机制:/etc/shadow 九字段
-S 与所有改密参数的最终落点都是 /etc/shadow,先看三个测试账号的原始记录:
$ grep -E "^(u4c1|u4c2|u4c3):" /etc/shadow
u4c1:$y$j9T$4PIYpGVX1ZJ5omzB9OrdI.$QsE5AqJniEckNFmttyTEQ8uskwpFbDs7M4PfKemqVs0:20741:0:99999:7:::
u4c2:$y$j9T$pjqvgUufnri97AqVfFjmC/$cxpZmtqvIlDIHqKovBDmisToFTAQqrRbI.sAQmWopX3:20741:0:99999:7:::
u4c3:$y$j9T$zTNwUq.OscC16JrphqZoc0$6engaLcNLTKhzeujboAMptw4ZeCwq05x3FCHZPtgsN7:20741:0:99999:7:::
九个字段以冒号分隔:
| # | 字段 | u4c1 取值 | 含义 |
|---|---|---|---|
| 1 | 登录名 | u4c1 | 与 /etc/passwd 对应 |
| 2 | 口令哈希 | $y$j9T$… | 算法+盐+哈希;! 前缀=锁定;空=无密码 |
| 3 | 最后修改日 | 20741 | 自 1970-01-01 的天数(20741=2026-10-15) |
| 4 | 最小修改间隔 | 0 | 距上次修改多少天内不可再改 |
| 5 | 最大有效天数 | 99999 | 超过即要求改密 |
| 6 | 警告天数 | 7 | 到期前 7 天开始提示 |
| 7 | 不活跃宽限 | 空 | 过期后多少天账号停用 |
| 8 | 账号失效日 | 空 | 绝对失效日期(天数) |
| 9 | 保留 | 空 | 预留字段 |
💡 技术拓展:第二字段哈希前缀对应不同算法——
前缀 算法 说明 $y$ yescrypt Ubuntu 22.04 默认(基于 scrypt,抗 GPU 破解) $6$ SHA-512 Ubuntu 20.04 及传统 Linux 常见 $5$ / $1$ SHA-256 / MD5 老系统,强度低 ! 前缀 锁定标记 原哈希前加 !,见 3.4 的 -l 实测空 无密码 见 3.5 的 -d 实测(危险状态)
三、参数逐项实测
3.1 -S:查看口令状态(七字段解读)
不带用户名时查看当前用户(root 身份执行即查 root):
$ passwd -S
root P 10/15/2026 0 99999 7 -1
指定用户(root 可查任意账号):
$ passwd -S u4c1
u4c1 P 10/15/2026 0 99999 7 -1
$ passwd -S u4c2
u4c2 P 10/15/2026 0 99999 7 -1
$ passwd -S root
root P 10/15/2026 0 99999 7 -1
--status 是 -S 的长格式等价写法:
$ passwd --status u4c2
u4c2 P 10/15/2026 0 99999 7 -1
七个字段逐项解读(以 u4c2 P 10/15/2026 0 99999 7 -1 为例):
| # | 取值 | 含义 |
|---|---|---|
| 1 | u4c2 | 登录名 |
| 2 | P | 口令状态:P=已设置可用,L=锁定,NP=无密码 |
| 3 | 10/15/2026 | 最后修改日期 |
| 4 | 0 | 最小修改间隔(天),对应 shadow 第 4 字段 |
| 5 | 99999 | 最大有效天数,对应第 5 字段 |
| 6 | 7 | 到期警告天数,对应第 6 字段 |
| 7 | -1 | 过期后宽限天数,对应第 7 字段(-1=未设置) |
对照 3.7 策略修改前后的 -S 输出,可以直观看到第 4~7 字段的变化。
3.2 root 为指定用户交互式改密
root 执行 passwd 用户名,依次提示 New password / Retype new password(输入不回显,本例为演示按顺序送入):
$ { sleep 2; echo q1w2e3r5; sleep 1; echo q1w2e3r5; } | script -qec 'passwd u4c2' /dev/null
New password:
Retype new password:
passwd: password updated successfully
两次输入不一致时,流程中止且密码保持不变:
$ { sleep 2; echo q1w2e3r4; sleep 1; echo q1w2e3r5; sleep 1; echo q1w2e3r4; sleep 1; echo q1w2e3r4; } | script -qec 'passwd u4c2' /dev/null
New password:
Retype new password:
Sorry, passwords do not match.
passwd: Authentication token manipulation error
passwd: password unchanged
弱口令实测:本最小化环境未启用 pwquality 质量模块,123 被直接接受(完整版 Ubuntu 桌面/服务器启用 pam_pwquality 后会报 BAD PASSWORD: The password is shorter than 8 characters 并要求重试):
$ { sleep 2; echo 123; sleep 1; echo 123; sleep 1; echo q1w2e3r4; sleep 1; echo q1w2e3r4; } | script -qec 'passwd u4c2' /dev/null
New password:
Retype new password:
passwd: password updated successfully
改密后的验证(-S 日期字段刷新):
$ echo "u4c2:q1w2e3r4" | chpasswd
(无输出)
$ passwd -S u4c2
u4c2 P 10/15/2026 0 99999 7 -1
💡 说明:root 为用户设置口令时不需要旧口令、也绕过「新旧口令不能相同」类检查;上面第三条展示了本环境弱口令被接受的真实行为,生产环境应确认 pwquality 模块已启用。
chpasswd(拓展工具)是非交互替代,见 4.4。
3.3 普通用户自助改密(需先验证当前密码)
普通用户不带参数执行 passwd 时,先验证 Current password 再设新密码——这是「本人改密」与「root 代改」的核心区别:
$ { sleep 2; echo q1w2e3r4; sleep 1; echo q1w2e3r5; sleep 1; echo q1w2e3r5; } | script -qec 'su u4c2 -c passwd' /dev/null
Changing password for u4c2.
Current password:
New password:
Retype new password:
passwd: password updated successfully
当前密码错误时直接中止:
$ { sleep 2; echo wrongpass; sleep 1; } | script -qec 'su u4c2 -c passwd' /dev/null
Changing password for u4c2.
Current password:
passwd: Authentication token manipulation error
passwd: password unchanged
恢复演示口令并确认状态:
$ echo "u4c2:q1w2e3r4" | chpasswd
$ passwd -S u4c2
u4c2 P 10/15/2026 0 99999 7 -1
💡 说明:错误信息
Authentication token manipulation error是 PAM 层的通用失败描述,真实原因(旧密码错、两次不一致、密码未改等)看上下文行。「Authentication token」即口令在 PAM 中的内部称呼。
3.4 -l 锁定 / -u 解锁(含登录验证)
锁定 u4c3 并观察状态与 shadow 变化:
$ passwd -l u4c3
passwd: password expiry information changed.
$ passwd -S u4c3
u4c3 L 10/15/2026 0 99999 7 -1
$ grep "^u4c3:" /etc/shadow
u4c3:!$y$j9T$zTNwUq.OscC16JrphqZoc0$6engaLcNLTKhzeujboAMptw4ZeCwq05x3FCHZPtgsN7:20741:0:99999:7:::
锁定后即使输入正确的密码也无法通过认证(u4c2 借 su 尝试切到 u4c3):
$ { sleep 2; echo q1w2e3r4; sleep 1; } | script -qec "su u4c2 -c 'su u4c3 -c id'" /dev/null
Password:
su: Authentication failure
-u 解锁后恢复:
$ passwd -u u4c3
passwd: password expiry information changed.
$ passwd -S u4c3
u4c3 P 10/15/2026 0 99999 7 -1
再次借 su 切换,同样的密码这次成功:
$ { sleep 2; echo q1w2e3r4; sleep 1; } | script -qec "su u4c2 -c 'su u4c3 -c id'" /dev/null
Password:
uid=1010(u4c3) gid=1013(u4c3) groups=1013(u4c3)
💡 说明:
-l的实现是在哈希前加!(见 shadow 回显第 2 字段),使任何输入都匹配失败——所以 SSH/su/控制台登录全部被拒,状态从 P 变为 L。它锁定的是「口令认证」,不是账号本身(若配置了密钥登录,SSH 密钥仍可用;彻底停用账号要用usermod -L/chage -E 0并注意其副作用)。
3.5 -d:删除密码(危险操作)
$ passwd -d u4c3
passwd: password expiry information changed.
$ passwd -S u4c3
u4c3 NP 10/15/2026 0 99999 7 -1
$ grep "^u4c3:" /etc/shadow
u4c3::20741:0:99999:7:::
状态变为 NP(No Password),shadow 第 2 字段被清空。随后执行 -u 不再报「解锁无密码账号」类错误,而是仅刷新老化信息(实测回显),空字段保持为空:
$ passwd -u u4c3
passwd: password expiry information changed.
立即用 chpasswd 重设口令消除危险状态:
$ echo "u4c3:q1w2e3r4" | chpasswd
$ passwd -S u4c3
u4c3 P 10/15/2026 0 99999 7 -1
⚠️ 注意:
-d之后账号处于「无密码」状态,任何能触达登录入口的人都可能直接进入该账号,仅可用于受控的实验/一次性场景;日常停用请用 3.4 的-l。
3.6 -e:强制下次登录改密
$ passwd -e u4c2
passwd: password expiry information changed.
$ passwd -S u4c2
u4c2 P 01/01/1970 0 99999 7 -1
$ grep "^u4c2:" /etc/shadow
u4c2:$y$j9T$3Y6KMgxz7WImvySM9PZmE.$T0hpLPXgvBS99JxYcwrcqIX7H4PeyyFthv5eLliE5D6:0:0:99999:7:::
实现是把「最后修改日」置 0(即 1970-01-01,必过期)。此时 u4c2 登录(su - 进入登录 shell),PAM 会先强制走改密流程,成功后才进入 shell:
$ { sleep 3; echo q1w2e3r4; sleep 1; echo q1w2e3r5; sleep 1; echo q1w2e3r5; sleep 1; echo exit; } | script -qec 'su - u4c2' /dev/null
You are required to change your password immediately (administrator enforced).
Changing password for u4c2.
Current password:
New password:
Retype new password:
u4c2@f1034b9326b2:~$ exit
logout
改密完成后登录流程正常进入 shell(提示符出现)。重置演示口令后 -S 的日期恢复为当天:
$ echo "u4c2:q1w2e3r4" | chpasswd
$ passwd -S u4c2
u4c2 P 10/15/2026 0 99999 7 -1
💡 说明:
-e典型用途是管理员为新人初始化临时口令后强制其首登自改。流程提示「administrator enforced」表示 root 强制过期(区别于自然到期)。
3.7 -n / -x / -w / -i:有效期策略(与 -S 对照)
默认策略(0 99999 7 -1)改为「最短 7 天、最长 90 天、提前 14 天警告、过期后宽限 30 天」:
$ passwd -S u4c2
u4c2 P 10/15/2026 0 99999 7 -1
$ passwd -n 7 -x 90 -w 14 -i 30 u4c2
passwd: password expiry information changed.
$ passwd -S u4c2
u4c2 P 10/15/2026 7 90 14 30
-S 的第 4~7 字段同步变化(0→7、99999→90、7→14、-1→30)。可单独修改某一项,例如只改最长有效期为 45 天:
$ passwd -x 45 u4c2
passwd: password expiry information changed.
$ passwd -S u4c2
u4c2 P 10/15/2026 7 45 14 30
恢复默认(-1 表示撤销宽限设置):
$ passwd -n 0 -x 99999 -w 7 -i -1 u4c2
passwd: password expiry information changed.
$ passwd -S u4c2
u4c2 P 10/15/2026 0 99999 7 -1
$ grep "^u4c2:" /etc/shadow
u4c2:$y$j9T$M3kphoEm2yQPV74KhX3fg.$jhIhee6U4NV8ujYnnJkG6ibM0DpzOjoLXiiYiqiUJ16:20741:0:99999:7:::
💡 说明:这四个参数只写 shadow 的第 4~7 字段,不动哈希;批量基线化建议用
chage(shadow 自带的专职工具)或直接维护 /etc/login.defs 的全局默认。注意passwd -i -1中的-1是-i的参数值(撤销宽限),不是独立选项。
3.8 -k:仅在口令已过期时修改
-k(keep-tokens)要求「只有过期才允许改」。对未过期的 u4c2 实测:验证当前密码后被中止:
$ { sleep 2; echo q1w2e3r4; sleep 1; } | script -qec 'su u4c2 -c "passwd -k"' /dev/null
Changing password for u4c2.
Current password:
New password:
Password change has been aborted.
passwd: Authentication token manipulation error
passwd: password unchanged
💡 说明:
-k的用途是配合脚本在「口令已过期」时才让用户改密(如登录前的预警提示场景),未过期即中止,防止在错误的时间点刷新口令。
3.9 -q:安静模式
root 用 -q 为 u4c2 设置口令,实测输出与不带 -q 的 3.2 相同(提示符仍然出现):
$ { sleep 2; echo q1w2e3r5; sleep 1; echo q1w2e3r5; } | script -qec 'passwd -q u4c2' /dev/null
New password:
Retype new password:
passwd: password updated successfully
$ echo "u4c2:q1w2e3r4" | chpasswd
$ passwd -S u4c2
u4c2 P 10/15/2026 0 99999 7 -1
💡 说明:实测中
-q对本场景的提示行没有可见抑制效果——它主要抑制部分 shadow 工具的附加输出,不要指望-q隐藏提示符;若要「无输出执行」应改用 chpasswd。
3.10 -r:指定口令仓库
-r 选择口令数据所在仓库(本地文件为 files,nis/ldap 取决于编译与配置)。实测指定 files 仓库改密,行为与默认一致:
$ { sleep 2; echo q1w2e3r5; sleep 1; echo q1w2e3r5; } | script -qec 'passwd -r files u4c2' /dev/null
New password:
Retype new password:
passwd: password updated successfully
$ echo "u4c2:q1w2e3r4" | chpasswd
$ passwd -S u4c2
u4c2 P 10/15/2026 0 99999 7 -1
💡 说明:本机默认仓库就是 files,
-r files属于显式写法;集中认证环境(LDAP 等)中该参数决定改密落点。
3.11 -R:在 chroot 目录下操作
-R 把操作目标切到另一个根目录(救援/修复场景)。目标目录不存在时报错清晰:
$ passwd -R /nonexistent-u4c -S u4c3
passwd: cannot access chroot directory /nonexistent-u4c: No such file or directory
准备一个仅含 passwd/shadow 的最小目录,实测该模式下读取状态:
$ mkdir -p /tmp/chroot-etc && cp /etc/passwd /etc/shadow /tmp/chroot-etc/
$ passwd -R /tmp/chroot-etc -S u4c3
passwd: Cannot determine your user name.
💡 说明:chroot 模式要求目录内具备完整的账户数据库与运行环境(仅拷贝 passwd/shadow 不足以完成涉及「当前用户解析」的操作,实测即报
Cannot determine your user name);它主要面向救援盘/系统修复场景,日常管理不需要-R。
3.12 -a:全账号状态巡检(-aS)
-a 需与 -S 连用,root 一次列出全部账号状态。以下为实测输出节选(中间略去部分系统账号):
$ passwd -aS
输出节选(实测,首尾):
root P 10/15/2026 0 99999 7 -1
daemon L 09/24/2026 0 99999 7 -1
bin L 09/24/2026 0 99999 7 -1
sys L 09/24/2026 0 99999 7 -1
sync L 09/24/2026 0 99999 7 -1
games L 09/24/2026 0 99999 7 -1
man L 09/24/2026 0 99999 7 -1
lp L 09/24/2026 0 99999 7 -1
mail L 09/24/2026 0 99999 7 -1
news L 09/24/2026 0 99999 7 -1
uucp L 09/24/2026 0 99999 7 -1
proxy L 09/24/2026 0 99999 7 -1
www-data L 09/24/2026 0 99999 7 -1
backup L 09/24/2026 0 99999 7 -1
list L 09/24/2026 0 99999 7 -1
irc L 09/24/2026 0 99999 7 -1
gnats L 09/24/2026 0 99999 7 -1
nobody L 09/24/2026 0 99999 7 -1
_apt L 09/24/2026 0 99999 7 -1
……(中间为其他系统与服务账号)
sshd L 10/15/2026 0 99999 7 -1
u4c1 P 10/15/2026 0 99999 7 -1
u4c2 P 10/15/2026 0 99999 7 -1
u4c3 P 10/15/2026 0 99999 7 -1
💡 说明:巡检要点——系统账号几乎全是 L(锁定,本就无口令),P 为有效口令账号;若出现 NP(无密码)应立即整改。配合
passwd -S 用户名做定点复核。
3.13 权限边界与错误用法
普通用户不能查看/修改他人信息:
$ su u4c1 -s /bin/bash -c "passwd u4c2"
passwd: You may not view or modify password information for u4c2.
$ su u4c1 -s /bin/bash -c "passwd -S u4c2"
passwd: You may not view or modify password information for u4c2.
不存在的用户:
$ passwd -S nosuchuser-u4c
passwd: user 'nosuchuser-u4c' does not exist
💡 说明:普通用户唯一合法形态是
passwd(改自己的,见 3.3)与passwd -S/passwd -r 仓库 -S(查自己的)。root 的边界仅受 shadow 数据库约束。
四、实战示例
4.1 新账号口令初始化(设置 + 基线策略 + 强制首改)
组合 chpasswd(非交互设置)→ -n/-x/-w/-i(策略)→ -e(强制首改)→ -S(验证):
echo 'u4c2:q1w2e3r4' | chpasswd # 非交互设初始口令
passwd -n 7 -x 90 -w 14 -i 30 u4c2 # 90 天有效期、提前 14 天警告
passwd -S u4c2 # 验证策略
passwd -e u4c2 # 强制下次登录改密
passwd -S u4c2 # 验证过期标记
策略写入后(实测,见 3.7):
u4c2 P 10/15/2026 7 90 14 30
执行 passwd -e u4c2 后(实测,见 3.6,最后修改日变为 1970-01-01 即首登必改):
u4c2 P 01/01/1970 0 99999 7 -1
4.2 离职/临时停用账号(-l 锁定 → 验证 → -u 恢复)
按 3.4 实测:passwd -l u4c3 后 -S 显示 L、shadow 哈希带 ! 前缀,即使密码正确 su 也报 su: Authentication failure;人员返聘时 passwd -u u4c3 一条恢复。全流程命令:
passwd -l u4c3 && passwd -S u4c3 # 锁定并确认 L
passwd -u u4c3 && passwd -S u4c3 # 解锁并确认 P
4.3 脚本化批量设置口令(chpasswd,非交互)
passwd 是交互式程序,脚本里批量设置口令用 chpasswd 替代(本篇实测中多次使用):
$ echo "u4c2:q1w2e3r4" | chpasswd
(无输出,成功即静默;配合 passwd -S u4c2 验证为 P 10/15/2026,见 3.2/3.3 的验证回显。)
⚠️ 注意:口令会出现在命令行/管道中,脚本应避免把真实口令写进代码(用变量从受控配置读取),并注意 shell 历史记录。
4.4 口令合规巡检(-aS 找异常)
按 3.12:passwd -aS 全量过一遍,重点盯 NP(无密码)与不该出现的 P(系统账号被设了口令);对可疑账号用 passwd -S 用户名 定点复核,用 -l 紧急锁定。本机实测中全部系统账号均为 L 状态、三个测试账号为 P 状态。
4.5 密码过期演练(-e + 登录验证)
按 3.6 完整流程:passwd -e u4c2 → u4c2 登录即见 You are required to change your password immediately (administrator enforced). → 依次输入当前/新/重复口令完成改密后进入 shell。该流程可用于上线前验证「强制改密」是否符合预期。
五、注意事项与常见问题
Q1:passwd: Authentication token manipulation error 是什么意思?
PAM 通用失败报错(口令在 PAM 中称 authentication token)。3.3 的当前密码错误、3.7 前后的流程异常都可能出现,需结合前后输出定位(如 password unchanged 表示本次未改)。排查顺序:PAM 日志(/var/log/auth.log)→ 模块配置(/etc/pam.d/common-password)→ 文件锁(/etc/passwd.lock 等残留)。
Q2:脚本能直接跑 passwd 用户名 吗?
不能可靠实现——passwd 必须从终端交互读密。脚本路径有二:chpasswd(本篇 4.3 实测)或 usermod -p 哈希值(直接写哈希,需自行生成)。本篇交互流程均通过「伪终端分步输入」实测完成。
Q3:-l 锁定后用户还能登录吗? 口令登录全部被拒(3.4 实测 su 报 Authentication failure,SSH 密码登录同理);但若账号配置了 SSH 公钥且 sshd 允许,密钥登录不受 shadow 哈希影响——彻底停用需组合 usermod/chage 并检查 SSH 授权。
Q4:为什么 root 改密不提示 BAD PASSWORD,普通用户会?
口令质量策略由 PAM 模块(pam_pwquality 等)执行:对 root 通常只告警不阻断,对普通用户阻断。本最小化环境未启用 pwquality,3.2 中 123 被 root 直接接受(实测);完整版系统会输出 BAD PASSWORD: The password is shorter than 8 characters。
Q5:-S 输出里的日期为什么可能是 01/01/1970?
最后修改日被置 0(shadow 第 3 字段为 0),即 3.6 的 -e 强制过期效果,登录时必被要求改密;改完日期恢复为当天。
Q6:-d 删除密码和 -l 锁定哪个安全? 都不要用 -d 表达「停用」语义——NP 状态等于无密码(3.5 实测 shadow 字段为空);停用一律用 -l(或 usermod -L),并用 -S 确认 L 状态。
Q7:修改了有效期策略但用户仍能一直不改密? 检查三点:shadow 第 5 字段是否真的生效(-S 第 5 列,见 3.7 对照);是否还有「绝对过期」(-e 或 chage 设置);系统是否启用了过期检查的 PAM 配置。策略只写在 shadow 里,读取执行由 PAM/login 完成。
六、参考链接
- shadow-utils 官方上游(Shadow):https://github.com/shadow-maint/shadow
- passwd(1) 手册(Ubuntu 22.04 jammy):https://manpages.ubuntu.com/manpages/jammy/man1/passwd.1.html
- shadow(5) 手册(/etc/shadow 格式):https://manpages.ubuntu.com/manpages/jammy/man5/shadow.5.html
- chpasswd(8) 手册:https://manpages.ubuntu.com/manpages/jammy/man8/chpasswd.8.html
- chage(1) 手册(口令老化管理):https://manpages.ubuntu.com/manpages/jammy/man1/chage.1.html
- Linux PAM 官方文档:https://github.com/linux-pam/linux-pam