☰
Linux passwd命令全面解析:账户安全、密码策略与常见排障实践
2026/10/13 7:24:00 网站建设 项目流程

在Linux系统管理里干得越久,越会发现一个规律:越是天天用的基础命令,越容易被人低估。passwd命令就是最典型的例子。绝大多数人对它的理解停留在"给自己改个密码"这个层面,但实际上它承担着Linux账户安全体系里最核心的认证信息管理职责——改密码、锁账户、设置过期策略、强制重置,背后都是这一个命令。这篇文章我不打算只念man手册,而是把我自己从入门到负责多台服务器账户管理的实操经验完整摊开:passwd的正确用法、它背后的权限模型和文件机制、踩过的坑以及对应的排查思路。无论你是刚摸到Linux命令行的新人,还是需要批量管理账户的运维,都可以对照这篇内容直接上手。

1. 为什么Linux账户安全绕不开passwd

1.1 一个命令,三层身份

passwd表面上是"设置密码",但它实际干的事情比这复杂得多。它会根据当前执行者的身份来决定允许做什么、不允许做什么,这套规则背后是Linux最基本的权限模型。

  • 普通用户:只允许修改自己的密码,而且必须先输入原始密码验证身份。这一步没什么可讨价还价的,root之外的任何用户都绕不过去。
  • 管理员(root):可以修改任意用户的密码,不需要知道该用户原来的密码,也不需要输入任何旧密码。这是提权操作,也是日常运维里最常用的场景。
  • 系统服务用户:比如运行数据库或Web服务的专用账户,通常无法直接登录。但通过passwd -S可以查看它们的密码状态,配合passwd -l可以彻底锁死这些账户,防止有人趁虚而入。

我见过不少新手试图用vi直接打开/etc/shadow去改密码,理由很简单:"哈希不就在这个文件里吗,我替换掉不就行了?"技术上确实可行,但实际环境里几乎没人这么干,原因有三层。

第一,/etc/shadow的权限极其敏感,默认只有root能读,普通用户连看都看不到,更别说改了。第二,密码哈希的算法和格式有严格约定——$6$代表SHA-512,$y$代表新版yescrypt,老系统还有$1$的MD5,手改文件时哪怕漏掉一个字符,整行失效,这个账户就再也登不进去了。第三,也是最重要的,直接改文件会绕过PAM、密码策略、审计日志等一系列机制,出了问题连排查线索都没有。passwd命令存在的意义,就是给这些底层操作提供一个安全、可靠、带完整校验的封装接口。

1.2 密码不是"存起来"的,是"算出来"的

理解passwd命令之前,得先弄明白Linux到底是怎么存密码的。很多人以为是明文存在某个文件里,这是最危险的误解。实际上,/etc/shadow里存的是密码的哈希值——一段由密码经过不可逆算法计算出来的固定长度字符串。

登录时系统做的事情是:把你输入的密码用同样的算法再算一遍,然后和shadow文件里存的哈希做比对。哈希加密算法本身是不可逆的,也就是说,就算攻击者拿到了shadow文件,也无法直接还原出原始密码,只能靠暴力字典去撞。

这种设计意味着一个很现实的问题:密码本身的强度,直接决定了整个认证体系的安全下限。passwd命令修改密码时,会调用系统的密码质量检查组件(PAM体系里的pam_pwquality模块),对长度、字符种类、重复度做校验。这就是为什么有时候你设置"123456"会被系统一脸嫌弃地拒绝——不是命令故意刁难你,而是它身后站着一整套密码策略。

我用一个生活化的类比:哈希算法就像一台碎纸机,密码进去,变成一堆纸屑,系统只保存纸屑的模样。你下次登录时,把新打印的密码再塞进去,看碎出来的纸屑是不是一模一样。碎纸机不可逆,但比对结果却可以100%确定。passwd命令,就是这台碎纸机前面那个带身份验证的操作员。

2. 基本用法拆解:报错、选项和日常操作

2.1 普通用户修改自己的密码:最基础也是最容易出错的一步

普通用户登录系统后,直接执行passwd,不带任何参数,系统就会进入交互流程。它会先要求你输入当前密码,再让你输入两次新密码。这里有几个细节是新手最容易栽跟头的。

第一,输入新密码时屏幕不会有任何回显,连星号都没有。很多人以为键没生效,其实是在正常输入,只是系统主动屏蔽了显示。这个行为继承自/etc/login.defs里的终端回显配置,是防偷窥的常规做法。

第二,两次输入新密码不一致时,系统会提示"passwords do not match",然后要求重新走一遍流程,而不是只让你重新输入第二遍。我见过不少人在这里反复纠结,以为是自己的键盘出了问题,其实只是两次打的内容不一样。

第三,新密码必须在短时间内完成设置。如果超过一定时间(通常是几秒到几十秒,取决于PAM配置),整个流程会超时终止,需要重新执行命令。这是防止终端被占着、密码被晾在屏幕上的安全策略。

普通用户修改自己的密码时,如果设置的密码太简单、太短、或者和用户名太相似,同样会被PAM策略拦下来。比如在默认的passwd配置下,你设置纯数字的8位密码,大概率会收到类似"BAD PASSWORD: it is too simplistic/systematic"的提示。这时候不要硬刚系统,老实用一个满足复杂度要求的密码更明智。

2.2 管理员修改指定用户密码:一次性搞定root和运维的日常

作为root,给某个用户改密码非常简单:

passwd username

执行后系统会直接提示输入新密码,不会要求输入旧密码。如果你在输入用户名时拼写错误,系统会提示"user 'username' does not exist",所以执行之前先确认一遍账户名总没错。

这里有一个非常实用的小技巧。脚本批量改密码时,可以用--stdin选项从标准输入读取密码,实现非交互式修改:

echo "NewPassword2025!" | passwd --stdin username

但要注意,--stdin不是所有发行版都支持。我在CentOS和RHEL上用得很顺手,但换成某些基于Debian的系统时,passwd会直接忽略这个选项,命令静默失败。这时候我一般改用chpasswd:

echo "username:NewPassword2025!" | chpasswd

chpasswd是另一个专门用于批量更新密码的工具,它支持从标准输入读取"用户名:密码"格式的多行内容,特别适合脚本里批量重置多个账户的场景。

还有一个操作要提醒:千万别在生产环境长期使用--stdin配合明文密码写在脚本里。脚本文件如果权限配置不当,任何一个能读到文件的用户都等于拿到了所有密码。我的习惯是:脚本执行完立刻清理历史记录,脚本文件权限至少设为700,并且定期轮换这些账户的密码。

2.3 选项速查表:一张表讲清楚常用参数

选项作用典型使用场景注意事项
-d删除密码配合锁定策略,让账户完全无法密码登录删密码后账户极不安全,非必要不用
-l锁定账户员工离职、临时停权锁定是在哈希前加!,不是删除密码
-u解锁账户恢复被锁定的账户只对-l加的锁生效,对因过期自动锁定的账户无效
-e使密码立即过期强制用户下次登录改密码和chage -d 0行为一致
-x设置密码最大有效天数落实密码定期更换策略与/etc/login.defs里的PASS_MAX_DAYS对应
-n设置密码最小修改间隔防止用户改了又马上改回旧密码配合-x一起使用才成体系
-w设置过期前警告天数提前提醒用户换密码默认通常是7天
-i设置不活跃天数密码过期后多久彻底锁定账户超过该天数后必须管理员介入
-S查看密码状态快速检查账户锁定/过期情况字段含义见下文,别只看第一个字符

-S的输出很多人看不懂,这里举个例子:

username P 03/13/2024 0 99999 7 -1

从左往右依次是:用户名、密码状态、上次修改日期、最小修改间隔、最大有效天数、警告天数、不活跃天数。第二个字段只有三种取值:P表示可用,L表示被-l锁定,NP表示没有设置密码。我排查账户问题时,第一条命令永远是passwd -S,因为它能在一行内告诉我这个账户的密码处于什么状态,省得去翻shadow文件。

3. 用passwd管理密码生命周期:过期、锁定与强制修改

3.1 账户锁定:-l与-u的真实行为

passwd -l username锁定账户,这件事本身不复杂,但我需要讲清楚它底层做了什么,因为这会直接影响你后面解锁的方式。

执行-l后,系统会在/etc/shadow里该用户密码哈希的最前面加上一个!字符。密码哈希一旦变成!$6$...这样的形式,系统在做比对时就会因为这个!而直接判定不匹配,等于作废了原来的密码。账户因此无法再用密码登录。

这里有个很关键的点:-l并没有删除密码哈希,只是用!把它临时停用了。所以对应的-u操作,就是把那个!去掉,恢复原来的哈希,密码也就恢复了。你可以用passwd -S确认:带锁的账户会显示L,解锁后恢复为P。

但实际操作中我经常遇到另一种情况:账户不是被-l锁的,而是因为密码过期太久、超过-i设置的不活跃天数后被系统自动锁定的。这种锁定在shadow文件里的表现是过期时间字段早已超过当前日期,而不是哈希字段带!。这时候你去执行passwd -u,系统会冷酷地回你一句"Account is locked"(具体提示因发行版而异),然后什么都不做。

正确的处理方式是先重置密码或修改过期日期。比如先passwd username设置一个新密码,再用chage -E -1 username清除账户过期日,或者用chage -I -1 username把不活跃天数设为无限制。我把这两种锁定叫"手动锁"和"策略锁",处理逻辑完全不同,这个区分在排查问题的时候能省下很多时间。

老实说,passwd -l这个命令在阻止用户登录这件事上并不是彻底的。如果用户的SSH登录方式是密钥认证,而服务器又没有限制PermitRootLogin和PasswordAuthentication,那么即使密码被锁,用户依然可以靠密钥登录。所以锁密码只是第一道闸,真正要禁止账户登录,还得配合usermod -L或者直接修改SSH配置。运维里没有"一招鲜"的说法,多层防护才是常态。

3.2 密码过期与强制修改:让新用户第一件事就是改密码

新入职的同事要开一个账户,管理员可以先给它一个临时密码,然后用一条命令让这个密码作废,强制对方首次登录时修改:

passwd -e username

-e的作用是把"上次修改密码的日期"直接设为1970年1月1日。系统看到这个日期,会认定密码早在半个世纪前就该换了,于是强制用户登录成功后立刻进入改密码流程。这和chage -d 0 username是等价的。

这个机制在实际使用中有个顺滑的体验:用户用SSH登录时,会收到类似"WARNING: Your password has expired. You must change your password now and login again!"的提示,然后被引导进入修改密码的交互界面。改完密码后,原连接会被断开,用户需要用新密码重新登录一次。这是正常流程,不是故障。

批量开户时,我通常把这几条组合在一起写进初始化脚本:

# 创建用户并设置临时密码 useradd -m -s /bin/bash username echo "TempPass2025" | passwd --stdin username # 强制首次登录修改密码 passwd -e username # 设置密码策略:最长90天,提前7天警告,过期后30天禁用 passwd -x 90 -w 7 -i 30 username

这里有个细节要特别说明:passwd -x、-w、-i设置的策略,最终写进的是用户在/etc/shadow里对应字段的值,而不是修改/etc/login.defs里的全局默认值。全局策略对所有新建用户生效,而passwd -x这类命令只对指定用户生效,两者是"全局默认+个体覆盖"的关系。

3.3 与chage命令的分工

提到密码过期和策略,就不能不提chage。它和passwd在密码生命周期管理上的分工一直是很多人搞不清楚的地方。

简单来说,passwd侧重"当前状态的改变"——改密码、锁账户、让密码马上过期;chage侧重"时间策略的查看和设置"——密码什么时候到期、账户什么时候失效。它们的操作目标虽然是同一个shadow文件里的字段,但打开的角度不同。

我日常用得最多的其实是chage -l:

chage -l username

这条命令会列出该用户完整的密码时效信息:上次改密时间、最短间隔、最长有效期、警告天数、不活跃天数、账户过期日期。这些信息在passwd -S里被压缩成了一行紧凑输出,chage -l则用人类友好的格式展示,排查用的首选。

设置策略时,两者其实可以互相替代:passwd -x 90和chage -M 90是同一件事。我个人习惯是:临时性操作(比如今晚就让某个账户过期)用passwd,系统性的策略梳理(比如月底巡检所有账户的过期日期)用chage -l。命令本身没有高下之分,关键是哪个用起来更顺手、更不容易出错。

4. 换密码背后的文件系统:passwd、shadow和login.defs如何协作

4.1 shadow字段逐段拆解

执行完passwd之后,到底改了什么?答案都在/etc/shadow里。这个文件每一行对应一个用户,用冒号分成9个字段,绝大多数情况下我们只需要关注前几个。

拿一条示例来说明:

username:$6$randomsalt$hashvalue:19254:7:90:7:30:19450:

第一个字段是用户名,没什么好说的。第二个字段是密码哈希,前面说的!锁定标记也加在这里。第三个字段是上次改密的日期,单位是"从1970年1月1日起的天数",所以passwd -e做的事情就是把这个数字改成0。第四个字段是最短修改间隔天数,第五个是最大有效天数,第六个是过期前警告天数,第七个是过期后不活跃天数,第八个是账户绝对过期日期(同理,也是天数),最后一个字段是保留位。

这套字段设计得非常简洁,但它把密码管理的所有时间维度都覆盖了。你可以回头看passwd -S的输出,就是把这几个字段压缩成了更紧凑的格式。所以假如哪天passwd -S的输出让你摸不着头脑,又不想看man手册,直接打开/etc/shadow对照这个结构逐段读,反而是最直观的。

需要记住的一个操作纪律:正常路径永远不要手动编辑/etc/shadow。这个文件如果格式损坏,会直接影响所有账户的登录认证,甚至导致整个系统无法登录。真有特殊需求,要么用系统提供的vipw命令(它会加文件锁并校验格式),要么老老实实用passwd、chage这些正规工具。我见过不止一次因为拖拽/替换shadow文件导致系统彻底无法登录的案例,最后只能通过救援模式修复,代价相当大。

4.2 密码哈希是怎么算出来的

当passwd写入新密码时,系统会调用crypt()库函数,把密码和一个随机盐值(salt)一起送进哈希算法。这个过程有几个要点值得说清楚。

第一,每次生成哈希都会用不同的随机盐值。哈希算法虽然不可逆,但如果没有盐值,相同密码在不同用户身上会生成完全相同的哈希,攻击者只要破解一次就能批量撞库。加了随机盐之后,即使两个用户的密码一模一样,shadow文件里存的哈希也完全不同。这个设计大大增加了字典攻击的难度。

第二,哈希算法的选择是有进化的。早期Linux用DES,后来升级到MD5,再后来是SHA-512,现在新发行版已经在转向yescrypt。你可以从哈希字符串的前缀一眼看出算法类型:$1$是MD5,$5$是SHA-256,$6$是SHA-512,$y$是yescrypt。如果我维护的服务器上有用户的哈希还是$1$开头,我会认为那是历史遗留账户,需要重点关注。

第三,更快的算法不等于更好的算法。对登录认证来说,哈希计算耗时控制在几十到几百毫秒是有意的设计——太快了反而容易让攻击者暴力破解上万次。你可能会觉得登录时有点慢,这恰恰是安全性的代价。

4.3 login.defs决定默认策略

执行passwd时,系统怎么知道新密码至少要多少位、或者密码最长能用多久?答案有一部分在/etc/login.defs里。

这个文件里有一组和密码策略直接相关的参数:

PASS_MAX_DAYS 90 PASS_MIN_DAYS 7 PASS_WARN_AGE 7

它们定义了新建用户时默认继承的密码时效策略。比如PASS_MAX_DAYS 90意味着新用户90天后密码必须更换,PASS_MIN_DAYS 7则是两次修改密码至少间隔7天,防止用户改完密码立刻又改回原来的。

但有个容易踩坑的地方:PASS_MIN_LEN(最小密码长度)在大多数现代系统上已经不会生效了。原因是密码复杂度校验已经被PAM体系接管,由/etc/pam.d/passwd里的pam_pwquality模块负责,而它读的配置文件是/etc/security/pwquality.conf,不是login.defs。如果你还在login.defs里改PASS_MIN_LEN,然后惊讶地发现怎么改都不起作用,这就是原因。

pwquality.conf里的核心参数包括minlen(最小长度)、dcredit(数字字符要求)、ucredit(大写字符要求)、lcredit(小写字符要求)、ocredit(特殊字符要求)、maxrepeat(最大重复字符数)等。其中dcredit = -1表示密码里必须包含至少一个数字,如果设为正数则表示最多允许出现多少个数字。默认情况下这些参数在很多发行版里是注释掉的,需要管理员按需放开。

我要提醒的是:策略是你业务安全的底线,但也是可用性的敌人。我见过有些团队为了满足"合规"把密码复杂度拉满,结果员工把密码贴在显示器上。一套合理的密码策略应该至少保证:长度不低于12位,包含三种以上字符类型,禁止连续重复字符,同时定期轮换。总结成一句话:让机器挡下最基础的攻击,别让用户崩溃到把密码抄在便利贴上。

5. 实战排查:passwd命令最常见的报错场景

5.1 "Authentication token manipulation error":先看文件权限,再看磁盘

这个报错应该是passwd命令里最让我印象深刻的一个了,因为它的出现时机总是很微妙——一般在生产环境、在你有急事的时候。

先解释这句话本身:"认证令牌操作失败",听着很抽象,其实就是系统在更新密码信息时失败了。常见原因按出现频率排序是这样的。

第一,/etc/shadow或/etc/passwd文件被意外设置成了只读。我曾经在加固服务器时执行过chattr +i /etc/passwd来防止篡改,结果后续改密码时就开始报这个错。用lsattr检查一下两个文件的权限位,如果看到i属性,chattr -i去掉即可。

第二,磁盘空间满了。/分区打满时,任何文件写入都会失败,shadow文件也不能幸免。df -h看一眼,把空间释放出来再试。

第三,PAM配置环节出了问题。/etc/pam.d/passwd这个文件如果被改坏,或者相关的pam_unix.so库文件被误动,一样会报错。这种相对少见,但排查起来最费劲,得翻/var/log/secure或/var/log/auth.log看具体日志。

第四,SELinux打开且安全上下文搞乱了。如果前面几条都查完没问题,建议看一下ausearch -m AVC -ts recent里有没有SELinux拒绝记录。临时用setenforce 0验证一下是否是SELinux导致的,但别长期关着。

我给一个通用的排查链路:先看lsattr和ls -l确认文件权限,再看df -h确认磁盘,然后tail认证日志看有没有PAM报错,最后才考虑SELinux。这个顺序我总结为"从最可能的开始,从最便宜的验证开始"。

5.2 PAM策略拦截:说好的8位密码怎么老被拒

另一个常见的"问题",其实是系统在认真履行职责。很多用户设置密码时被passwd拒绝,给出的提示是:

BAD PASSWORD: The password is too short BAD PASSWORD: The password fails the dictionary check

这不是bug,是pam_pwquality模块在干活。它按照/etc/security/pwquality.conf里的规则逐项检查你的密码:长度够不够、字符种类全不全、有没有连续重复、是不是和用户名过于相似。任何一个不满足,都会拒绝。

遇到这种情况,我的建议分两步走。第一步,先确认这个密码是不是真的不行——比如只有8位纯数字、或者包含了用户名。如果确实不行,换一个更复杂但自己记得住的密码,别和系统对着干。第二步,如果是团队的安全策略调整后误伤了很多账户,那就得考虑在pwquality.conf里微调参数,把过于严苛的项放开。比如把minlen从12降到10,或者把maxrepeat从2放宽到3,让策略更符合实际使用场景。

这里我要特别提一句:不要为了跳过策略检查去改PAM配置让密码走"旁路"。有些教程会教你直接绕过pam_pwquality,把passwd命令背后的校验模块删掉,这在我眼里就是自废武功。密码策略是系统抵御暴力破解的第一道防线,绕过它就等于把大门敞开。

5.3 忘记root密码的救援流程:最后的兜底方案

总有人会把root密码忘掉,或者某次加固之后把所有钥匙都锁在了保险柜里。这种情况下的兜底方案有几种,但它们都有一个共同前提:你能物理接触到这台服务器,或者至少有控制台级别的访问权限。

在系统启动时进入GRUB菜单,按e编辑内核启动项,在linux那一行末尾加上rd.break(针对CentOS/RHEL系列,它会让你进入一个临时根环境)或者直接加single(进入单用户模式,部分发行版适用)。挂载根文件系统后,用chroot进入真正的系统环境,执行:

passwd root

这是一个完全正常、在所有Linux系统管理文档里都有记载的恢复流程。重置密码后记得处理SELinux的重标记问题(在启用SELinux的系统上,需要创建一个/.autorelabel文件),然后重启。

说句实在话,在服务器上准备一张离线救援盘、或者提前把GRUB的进入方式记录下来,会大大减少你半夜抢险的痛苦。我自己的习惯是:每一台重要服务器都会在机房的密码管理箱里留一份"救援速查卡",上面写着这台服务器的GRUB启动流程、键盘布局特殊设置、以及进入救援模式后最常用的几条命令。卡片丢失的风险看起来不高,但真到用的时候没有,那就只能对着屏幕抓瞎了。

一些经验之外的补充:passwd命令的边界感

最后再多说两句我自己在长期使用中的体会。

第一,passwd命令解决的是"密码本身"的问题,但很多系统问题不是密码能解决的。比如用户明明输入了正确密码却被拒绝登录,可能是SSH配置禁用了密码登录,可能是PAM的account模块判定账户过期,甚至可能是/etc/nologin文件的存在阻止了所有非root用户登录。这时候你拼命去改密码是没用的,先确认问题到底出在哪一层,再决定要不要动passwd。

第二,尽量让passwd的变更走正规渠道。如果是企业环境,改密码这类操作最好和工单系统、审计系统联动。命令本身会写审计日志,但谁在什么时间为什么改了这个账户的密码,这些信息只能靠流程去覆盖。工具再强,也只是工具,真正决定安全性的,是使用工具的人有没有一套完整的操作规范和风险意识。

第三,多花几分钟验证,能省下后面几个小时。我每次批量重置密码后,都会挑几个账户用passwd -S和chage -l确认状态,然后挑一个账户实际登录一次。看似多花了时间,但比起夜里被用户喊醒说"我密码改了但登不上去",这点成本完全可以忽略。

passwd命令没有太多花哨的操作,但它横跨了密码安全、账户生命周期、PAM认证和系统排障多个领域。把这篇文章里的细节吃透,你在Linux账户管理上就基本不会遇到解决不了的问题了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询