
就用你现在最常看到的那台Linux服务器来说。无论是刚入行的运维新人还是写了几年脚本的老手passwd命令几乎天天见。它短、好记、语义直白大多数人对它的认知停留在“改个密码嘛敲两遍新密码就完事了”。但如果你真的在线上环境摸爬滚打过就会知道这条命令背后藏着一堆细节为什么有时候要你输入旧密码、有时候不用为什么 root 能改所有人的密码普通用户只能改自己的为什么明明密码改成功了桌面上还会弹一个“gkr-pam couldnt update the login keyring password”的报错密码策略到底怎么设置才符合等保要求这篇文章不打算只给你念一遍 man 手册我会把passwd从原理到实操、从常用参数到故障排查完整拆一遍配合真实案例和踩坑记录适合所有 Linux 使用者尤其是刚接触系统管理的朋友。1. 为什么一条基础命令值得你再学一次1.1 从“会改密码”到“懂改密码”很多人第一次用passwd是在练习环境里给自己的账户改密码。那时候的流程很简单输入passwd系统让你输入当前密码然后输两遍新密码完事。但到了真实的生产环境你会遇到这些场景新建了一个账号需要给账号设置初始密码还要让用户首次登录时必须改掉。某个员工离职了需要立即锁定他的账号密码防止他继续登录系统。服务器被扫描出弱口令你要批量把一批账号的密码统一重置。服务器的 root 密码忘了需要重启进单用户模式重置密码这个我在 3.4 节会详细写。登录时提示“password has expired”但你不知道该用哪个参数去调整有效期。桌面版 Linux比如 Ubuntu 带 GNOME 桌面的环境改完密码后弹出一个 “gkr-pam couldnt update the login keyring password” 的报错密码明明改成功了但每次登录都弹很烦。这些场景里passwd都不是那一句简单的“敲两遍新密码”能搞定的。它牵扯到 Linux 的账户认证体系、密码存储位置、密码策略、PAM 模块等一系列底层机制。所以把这条命令真正用明白能直接省掉你很多翻文档和熬夜排查的时间。1.2 passwd 命令的工作逻辑与底层机制passwd命令的核心作用是修改/etc/shadow文件里对应账户的密码哈希值。注意不是直接改/etc/passwd。这两个文件我简单对比一下文件存放内容权限说明/etc/passwd用户账号基础信息用户名、UID、GID、家目录、Shell所有用户可读早期 Unix 把密码哈希也放这里现在只放一个x占位符/etc/shadow密码哈希、最后一次修改时间、有效期、锁定状态等仅 root 可读密码真正存放的地方普通用户没有读取权限那为什么普通用户改自己密码时能写入/etc/shadow因为passwd命令本身带有 SUID 特殊权限。你可以执行ls -l /usr/bin/passwd看一下大概率会看到-rwsr-xr-x其中那个s就表示 SUID。这表示任何用户执行这个程序时都会以文件属主root的身份运行因此才有权限去改写/etc/shadow里自己那一行的密码哈希值。这是整个机制里最核心的一点理解了这一点你就能明白为什么普通用户只能改自己的密码而 root 用户能改所有人的密码——因为 root 本来就拥有一切权限不需要借助 SUID。密码存储方式上现代 Linux 几乎都使用 SHA-512 或更高强度的哈希算法哈希值存放在/etc/shadow的第二个字段格式通常是这样$6$salt$encodedhash$6$代表 SHA-512 加密中间的salt是随机生成的盐值后面那一长串是加了盐之后的哈希结果。passwd在验证旧密码时会用你输入的密码加上原来的盐值做哈希然后和 shadow 里的哈希比对验证通过后会用新密码重新生成盐值和哈希写回 shadow 文件。整个过程对用户是透明的但你要知道Linux 里不会也不能“还原”出你的明文密码它只有哈希校验这一条路。1.3 安全边界什么时候必须谨慎写这篇教程之前我必须先强调一个安全边界passwd是一个权力很大的命令尤其当你用 root 身份执行时可以重置任何账号的密码。这正是它能成为“恢复系统”利器的原因但也是一把双刃剑。只有在你明确拥有该系统的管理权限、或获得系统所有者授权的前提下才能重置别人的密码。不要为了省事给所有账号设置同一个弱密码哪怕只是测试环境。等保合规和内部审计查的就是这种东西。使用--stdin等非交互方式改密时命令会出现在 Shell 历史记录里。如果你是在共享机器上操作很容易把密码留在.bash_history中这是非常危险的习惯。后面的所有操作案例我都默认你是在自己管理的主机或虚拟机上执行。请把安全习惯摆正再继续往下看。2. 核心细节解析参数与使用要点2.1 常用参数一览passwd的参数并不算多但每个都有明确的用途。我把最常用的整理成一张表方便你查参数作用典型场景无参数修改当前登录用户的密码日常改密passwd 用户名root 修改指定用户的密码管理员重置用户密码-d删除用户的密码清空创建无密码账户一般不推荐-l锁定用户密码禁止登录员工离职、账号停用-u解锁用户密码恢复被锁定的账号-e强制用户下次登录时修改密码新账号首次登录改密-x 天数设置密码最大有效期等保合规要求密码定期更换-n 天数设置密码最小修改间隔防止用户频繁改回旧密码-w 天数设置密码过期前提醒天数提前通知用户改密-i 天数密码过期后账号多少天后被锁定账号安全管理-S查看用户密码状态排查用户锁定/过期问题--stdin从标准输入读取新密码脚本批量改密注意passwd -S在较新的发行版上也可以用--status代替输出格式基本一致。我在 CentOS 7/8、Ubuntu 18.04/20.04、以及国产的麒麟 V10 上都验证过-S参数都兼容可以放心用。2.2 状态查看与过期策略-S、chage、-e 的组合使用用passwd -S 用户名查看状态输出大概长这样tom L 09/14/2024 0 99999 7 -1这串输出的含义是用户名、密码状态L 表示锁定P 表示可用NP 表示无密码、最后一次修改密码的日期、最小修改间隔天数0 表示随时可改、最大有效期天数99999 表示永不过期、过期前提醒天数7 天、密码失效后的宽限天数-1 表示未设置。有没有觉得这个信息量很足但可读性一般所以我更推荐用chage -l 用户名来看人类可读的样式它会输出类似这样的内容Last password change : Sep 14, 2024 Password expires : never Password inactive : never Account expires : never Minimum number of days between password change : 0 Maximum number of days between password change : 99999 Number of days of warning before password expires : 7chage和passwd在密码老化管理上是互补的。passwd -x 90 tom可以设置 tom 的密码 90 天后过期但这和chage -M 90 tom是同一个效果。实操里我用chage会多一些因为它的输出更直观适合审计和自查。看到这里你可能会问那个-e参数到底什么时候用我举一个最常见的场景你给新同事创建了一个账号先用passwd tom设置一个临时密码然后再执行passwd -e tom强制 tom 下次登录时必须先改成自己的密码。如果没做这一步tom 就会一直用那个临时密码登录隐患很大。2.3 锁定和删除密码的边界-l和-d这两个参数也是新手容易搞混的。passwd -l tom的作用本质是在/etc/shadow中 tom 的密码哈希前面加了一个!前缀。这样用户输入正确密码去哈希比对时结果永远不会匹配自然也就无法登录。这个操作不会删除原密码哈希所以passwd -u tom可以随时把!去掉恢复原密码。passwd -d tom则是直接把密码哈希清空相当于“无密码”状态。此时 tom 登录系统不需要密码。在很多系统上这会让账号处于一种极其危险的状态因为任何人都可以直接登录。除非你明确要创建一个仅用于某种特殊服务、且不允许登录的无密码账户否则别用-d。而且即使是这样我也更推荐你用usermod -s /usr/sbin/nologin这类方式去限制登录而不是把密码删掉。在这个小节额外提醒一句passwd -l只锁密码不影响 SSH 密钥登录。如果用户本来就配置了 SSH 公钥锁密码之后他依然可以通过密钥登录系统。如果你想把用户的 SSH 登录也一起禁止需要配合usermod -L加usermod -s /sbin/nologin或者用chage -E 0把账号设置为立即过期这样才能形成一个相对完整的禁用策略。3. 实操案例从改密码到系统级重置3.1 场景一普通用户修改自己的密码这是最基础的操作但我要把完整的交互过程写出来因为实际输出对新手很有参考价值$ passwd Changing password for user tom. Current password: ← 这里输入当前密码屏幕上不会显示任何字符 New password: ← 输入新密码最好满足系统密码复杂度要求 Retype new password: ← 再输一遍新密码 passwd: all authentication tokens updated successfully.看到最后一行all authentication tokens updated successfully就说明改密成功了。这里有几个细节值得注意输入旧密码时如果连续输错passwd会直接报错退出不会给你无限制试错的机会。新密码如果太短、太简单、或者和旧密码太相似系统会根据/etc/pam.d/passwd里面的pam_pwquality或pam_cracklib规则拒绝接收并提示BAD PASSWORD。这不是系统故障是对密码强度的正常校验。密码输入全程没有任何回显不会显示***这是终端设计使然不是没敲进去。很多新手在这个环节会以为键盘坏了实际只是没有回显。3.2 场景二root 修改指定用户密码root 执行passwd tom时交互过程少了一个“当前密码”的步骤$ sudo passwd tom New password: Retype new password: passwd: all authentication tokens updated successfully.区别很明显root 改密不需要验证 tom 的旧密码这是系统赋予管理员的高权限操作。也正因如此所有 root 用户都要格外谨慎避免批量重置密码时手滑把某个服务账号的密码改了导致服务起不来。如果你是在一个允许 SSH 密钥登录的服务器上忘记某个用户密码时最快的方式就是用 root 执行passwd 用户名重置。前提是你有 root 权限或者能sudo su -切到 root。我个人的习惯是root 状态下手动改密码一定先whoami确认当前用户再执行passwd 目标用户。因为裸敲一个passwd改的就是 root 自己如果你本意是想改某个普通用户会直接把 root 密码改掉这种情况在线上环境不是没出现过影响面很大。3.3 场景三批量场景下的非交互改密有时候你需要在一个脚本里批量创建用户并设置初始密码。虽然 Linux 的passwd默认是交互式的但它支持从标准输入读取密码配合管道就能实现非交互式改密。具体写法如下echo NewPass123 | passwd --stdin tom这条命令的意思是把echo输出的字符串作为passwd的新密码输入。注意--stdin参数主要集中在 Red Hat 系列CentOS、Rocky、AlmaLinux上Debian 系Ubuntu、Debian默认不带这个选项。在 Ubuntu 上如果你硬要用会看到这样的报错Usage: passwd [options] [LOGIN] ...所以如果你是跨发行版操作我有一个更通用的方案用chpasswd命令echo tom:NewPass123 | chpasswdchpasswd默认从标准输入读取用户名:密码格式的内容批量改密特别方便比如配合一个用户文件while read user pass; do echo $user:$pass | chpasswd done userlist.txt有一个安全细节必须提醒这两种方式都会让密码出现在 Shell 历史记录里。解决方法是在命令前面加一个空格如果 Bash 配置了HISTCONTROLignorespace或者用unset HISTFILE临时关闭历史记录更稳妥的是把密码放进一个权限为 600 的文件里脚本读取后立即删除该文件。实测下来最稳的还是用ansible这类自动化工具管理密码变更把敏感信息交给 vault 存放而不是在命令行明文裸奔。3.4 场景四忘记 root 密码时的单用户模式重置在物理服务器或者虚拟机上如果 root 密码忘了实际是可以不重装系统、不丢失数据去重置的。这个操作在运维面试里也经常被问到。核心思路是通过引导菜单进入单用户模式或紧急模式以 root 权限挂载根文件系统然后用passwd重新设置 root 密码。以 CentOS 7/RHEL 7 系列为例完整步骤是重启系统在 GRUB 引导菜单出现时快速按e键进入编辑模式。找到以linux16开头的那一行定位到末尾的rhgb quiet在这两个参数后面加一个rd.break或者直接改成rd.break enforcing0这个区别我后面会说。按Ctrl X启动系统会进入一个switch_root环境的initramfs提示符。此时根文件系统是以只读方式挂载在/sysroot下的。执行mount -o remount,rw /sysroot把根重新挂载为可写。执行chroot /sysroot真正进入被遗忘密码的那个系统环境。执行passwd root设置一个新的 root 密码。如果之前加了enforcing0这里还需要额外处理 SELinux 标签问题。更推荐的做法是重置完密码后执行touch /.autorelabel让系统下次启动时自动修复文件安全上下文。输入exit退出 chroot再输入exit退出 initramfs系统会继续启动然后用新密码就可以登录了。Ubuntu 18.04 之后的新版系统流程略有不同在 GRUB 菜单按e把ro quiet splash这一行中的ro改成rw再在末尾加一个init/bin/bash启动后可以直接进入一个 root 的 shell然后执行passwd root重设密码。这种方式更直接因为它直接以可写方式挂载根分区并跳过了启动服务的加载。这里把rd.break和init/bin/bash两种方式做个对比对比项rd.breakRHEL 系init/bin/bashDebian 系目标进入 initramfs 的 switch_root 环境直接进入 root shell根挂载状态只读需手动 remount取决于是否把 ro 改为 rwSELinux 处理需 touch /.autorelabel一般需 touch /.autorelabel适用场景CentOS/RHEL/FedoraUbuntu/Debian关于这部分我想特别补充一句安全话题用这种方式进入系统不需要原密码说明物理访问权限本身就是一种“最高权限”。所以服务器的物理安全、BIOS 密码、GRUB 密码保护不能忽略。如果你管理的机器有外人可接触的地方建议给 GRUB 加个密码否则别人插个键盘就能把你的 root 密码换了。3.5 场景五从“普通用户重置 root 密码”到“登录流程重建”热搜词里有“vm虚拟机普通用户重置root用户密码”这个说法很多实验室环境里的虚拟机用户忘记 root 密码、但手上还有一个普通用户账号。那能不能直接通过普通用户重置 root严格来说普通用户的权限不足以修改/etc/shadow所以无法直接在登录状态下用passwd root改自己的 root 密码系统会提示Permission denied。能走通的路子只有两条普通用户有sudo权限执行sudo passwd root本质还是借助 root 身份完成重置。普通用户没有 sudo 权限需要重启系统走 3.4 里的单用户模式流程。因为在单用户模式下系统默认以 root 身份提供一个 shell不需要你输入任何密码。所以如果你在一台虚拟机上忘了 root 密码只要你能控制虚拟机的电源和引导就不需要重装系统3.4 的流程一定能救回来。这也是热词里“虚拟机重置 root”最常见的解法。4. 常见问题与排查技巧实录4.1 高频报错gkr-pam couldnt update the login keyring password这个报错在桌面版 Linux 上非常常见完整信息一般是passwd: password updated successfully passwd: gkr-pam couldnt update the login keyring password: no old password was entered从输出能看到密码本身是改成功了但 GNOME Keyring登录钥匙环没有同步更新导致每次登录桌面时都会弹窗让你输入旧密码来解锁钥匙环。这个问题对纯命令行服务器无影响但如果你用的是 Ubuntu 桌面版会非常恼人。出现原因主要是用户通过passwd命令改密时PAM 的pam_gnome_keyring模块尝试用旧密码去解密钥匙环文件但用户没有输入旧密码比如 root 强制重置或者钥匙环中的旧密码已经失效。解决办法有几种最直接的方法登录桌面后打开“密码和密钥”Seahorse右键点击登录钥匙环选择“更改密码”填写旧的系统密码然后设置为新的系统密码把钥匙环密码和系统密码重新同步。如果已经完全不记得旧密码可以删除当前用户的钥匙环文件让系统重建。文件一般位于~/.local/share/keyrings/删除login.keyring等文件后注销重新登录系统会重新创建一个空钥匙环以后每次登录自动用新密码解锁。命令行删除法在纯终端环境或 SSH 会话中也可以执行rm ~/.local/share/keyrings/login.keyring后重启会话。我踩过这个坑之后现在遇到桌面环境改密都会额外提醒一句别只盯着密码是否改成功还要检查钥匙环提示。否则用户第二天就会反馈“每次开机都弹窗”这个锅你背得很冤。4.2 密码策略导致的“新密码太简单”很多时候用户改密码会碰到类似这样的提示BAD PASSWORD: The password fails the dictionary check - it is based on a dictionary word这不是系统在刁难你而是 PAM 的密码质量控制模块在起作用。相关配置一般能在/etc/pam.d/passwd或/etc/pam.d/system-auth中找到常见的是pam_pwquality.so或pam_cracklib.so。它们会检查新密码的最小长度、是否包含大小写、数字、特殊字符以及是否和用户名相关等。我可以给你一个实际配置示例在/etc/security/pwquality.conf里minlen 12 dcredit -1 ucredit -1 lcredit -1 ocredit -1 minclass 3这段配置的含义是密码最短 12 位数字、大写字母、小写字母、其他字符各至少包含一位字符类别至少 3 种。如果你只是临时测一下不想为某个测试账户改策略可以直接用 root 执行echo SimplePass123 | passwd --stdin tom这种情况下root 改密码可以绕过部分密码复杂度检查至少我实测 CentOS 上是这样的但尽量别把这个当常规操作。生产环境里该有的密码复杂度策略还是要有不然内部合规检查那一关都过不去。4.3 用户锁定与密码过期问题速查我用一张表把常见的passwd相关状态和对应操作整理出来排查时可以对照参考问题现象可能原因排查/恢复方法登录提示Account locked密码被-l锁定passwd -u 用户名解锁登录提示Password expired密码超过最大有效期passwd -x -1 用户名取消过期或重设密码登录提示must be changed启用了-e强制过期正常改一次密码即可登录提示Permission denied密码输入错误次数过多, 或 PAM 锁定查看/etc/pam.d/login中的pam_faillock配置root 执行faillock --user 用户名 --reset账户在沉睡登录被拒密码过期后超过不活跃天数passwd -i -1 用户名取消失效宽限再重置密码passwd命令提示Cannot identify you用户名不存在id 用户名确认账号是否存在提示is not a valid user name用户名包含特殊字符或中文编码问题检查/etc/passwd里的实际用户名格式这里重点说说faillock这个玩意。很多系统默认开了失败锁定策略比如连续 5 次输错密码就锁定账号 15 分钟。但有些服务账号会被自动化脚本反复尝试登录可能触发这个策略导致账号被锁。这种时候别一上来就以为密码被改了先查faillock --user 用户名的输入输出把锁定记录清掉再试。4.4 中文用户名与特殊字符带来的怪问题有网友问“麒麟 v10 的中文用户密码忘了怎么重置”其实在基于 Linux 的系统里用户名的编码方式通常是 UTF-8所以中文用户名本身是能存在的比如张三。但是问题往往出在键盘布局、终端编码、字体渲染这些小细节上。如果你在一个纯字符界面上要重置一个中文用户的密码确实容易敲出乱码因为终端可能没配好中文字体。这时候我建议你这样做先用su -切到 root。用getent passwd | grep -P [\x{4e00}-\x{9fa5}]找到中文用户的原始用户名如果你能用中文输入法或复制粘贴的话。直接在命令行里写passwd 张三但确保当前终端编码是UTF-8并且有中文字体否则 shell 自己都能把用户名搞乱更别提密码了。如果实在输入不了中文可以用 UID 来定位awk -F: $31001 {print $1} /etc/passwd然后想办法用脚本匹配到用户名。这问题本质上和passwd命令本身没关系但现实中它就是会让很多使用者卡住。我遇到最省事的方案既然系统里有中文用户那你肯定有办法切换到图形界面或者远程桌面用图形终端重置中文用户密码最稳妥。另外密码中如果用了特殊字符比如$、!、、、空格在执行echo 密码 | passwd --stdin这类非交互方式时很容易被 Shell 解析出问题。我打个比方echo Pass$123 | passwd --stdin tom中$1在双引号里可能被当成 Shell 变量导致你实际设置的新密码根本不是你以为的那个。遇到这种场景请老老实实用交互式passwd或者用chpasswd加单引号字符串再或者把密码写进文件、从文件读取别直接在命令行里拼。5. 写在最后几个我踩坑后养成的习惯如果非要给这篇文章做个简单的收束我更愿意分享几个在实际操作中形成的习惯而不是复述命令怎么用。第一不要裸敲passwd。不管是 root 还是普通用户敲之前先明确你要改的是谁。生产环境里因为手滑把 root 密码改掉的案例我听过不止一次。宁可多打几个字符也不要裸敲。第二凡是涉及非交互式改密--stdin、chpasswd、脚本批量改都要额外小心 Shell 历史记录、特殊字符转义、以及执行后的确认。我会在执行完后马上用passwd -S 用户名或者chage -l 用户名检查状态确保密码真的改成功了而不是看一眼“命令成功”就放心。第三密码策略和安全配置一定要跟着系统版本走。CentOS 7 和老版本 Debian 的 PAM 配置差异不小写脚本前先确认一下/etc/pam.d/passwd里到底启用了哪些模块别把pam_pwquality和pam_cracklib混在一起更不要图方便注释掉策略不然你就是在给攻击者留门。第四重置密码后记得同步检查 SSH 密钥、sudo 配置、以及用户所属的组等关联信息。我们经常只关心“密码改成功没有”却忽略了密码只是认证链路里的一环。如果用户开着密钥登录那密码改成什么样都拦不住他如果 sudo 配置有漏洞重置密码也只是治标不治本。passwd这条命令本身很简单但围绕它的机制、安全策略和故障排查是整个 Linux 系统管理基本功里很值得花时间去吃透的一块。希望这篇教程能帮你少走一些弯路。