Linux用户密码过期时间查看与修改:chage与/etc/shadow实战
2026/9/24 12:31:19 网站建设 项目流程

做运维这行,早晚会碰到一个尴尬的场面:某个用户的密码过期了,人又不在电脑前,远程登录直接报“密码过期”,SSH 都进不去。用户打电话来催,你得在十分钟内搞清楚他密码是什么时候设的、什么时候过期、要不要改策略。这时候如果你只会重启服务器,那用户可能就要“重启”你了。

这篇文章专门讲 Linux 下如何查看和修改用户密码过期时间。覆盖面包括:chagepasswd -S、直接解析/etc/shadow文件,以及批量修改、过期提醒、常见坑点。适合系统管理员、运维新手、以及所有想把账号管理搞清楚的朋友。内容不绕弯子,全部是我在实际环境里验证过的操作和判断思路。

1. 用户与密码过期:先搞懂机制再动手

1.1 密码过期和账户过期,别傻傻分不清

很多人第一次接触这个问题时,会把“密码过期”和“账户过期”混为一谈。实际上这是两个完全不同的概念,处理方式也不一样。

密码过期指的是:用户登录时使用的密码已经超过了最大有效天数,登录界面会强制要求修改密码才能进入系统。换句话说,用户还能登录,只是必须先改密码。账户过期指的是:整个登录入口被禁用,无论密码是否正确、是否有效,都无法登录。这通常是管理员手动设置的一个绝对截止日期,或者账户被锁定后的表现。

举一个生活化的例子:密码过期就像是门禁卡到期了,你得去前台换一张新卡才能进门;账户过期则是你整个人被从系统名单里删掉了,就算卡还有效,门也不会给你开。运维时判断错这两者,可能会浪费大量排查时间。

在实际系统中,这两个属性分别由passwd的“max days”字段和/etc/shadow中的“account expiration”字段控制。chage -l命令的输出里会同时显示这两行,后面我会详细拆解。

1.2 关键配置文件:/etc/shadow 在背后搞了什么

不夸张地说,Linux 用户密码过期机制的核心全在/etc/shadow文件里。这个文件普通用户读不了,只有 root 或者有 sudo 权限的管理员能看。

一行典型的/etc/shadow记录长这样:

zhangsan:$6$9h4kDnXe$pWff...:19000:5:90:7:30:19250:

这行用冒号分成了 9 个字段,每个字段都有明确的含义:

  • 第 1 字段:用户名,这里是zhangsan
  • 第 2 字段:加密后的密码哈希。如果显示为!*,代表密码被锁定。
  • 第 3 字段:最后一次修改密码的日期,是从 1970 年 1 月 1 日到修改当天经过的天数。19000大约对应 2022 年年初。
  • 第 4 字段:两次修改密码之间的最小天数,即至少隔多少天才能再改。
  • 第 5 字段:密码的最大有效天数,超过这个天数后密码视为过期。90表示 90 天后必须改密码。
  • 第 6 字段:密码过期前多久开始提醒用户。7表示过期前 7 天开始警告。
  • 第 7 字段:密码过期后还能宽限登录的天数。30表示过期后 30 天内如果不改密码,账户将被禁用。
  • 第 8 字段:账户绝对过期日期,同样是从 1970 年开始计算的天数。如果为空,账户永不过期。
  • 第 9 字段:保留位,通常为空。

理解了这 9 个字段,后面所有的查看和修改操作都能对上号。chage命令本质上是帮你安全地读写这些字段,而手动编辑/etc/shadow虽然也能改,但风险很高,非必要不建议。

2. 查看用户密码过期时间:三条命令足够日常使用

2.1 chage -l 是最直白的查看方式

chage的全称是 change age,专门用来管理密码时效信息。最常用的查看参数是-l,它会把所有密码时效字段一次性展示出来,可读性非常好。

执行命令:

chage -l zhangsan

输出类似:

Last password change : Jan 05, 2024 Password expires : Apr 04, 2024 Password inactive : May 04, 2024 Account expires : never Minimum number of days between password change : 5 Maximum number of days between password change : 90 Number of days of warning before password expires : 7

逐行解读一下:

  • Last password change:上次修改密码的日期。
  • Password expires:密码过期日期,计算方式是上次修改日期 + 最大有效天数。
  • Password inactive:密码失效日期,计算方式是过期日期 + 宽限天数。在这个日期之前如果还不改密码,账户会被禁用。
  • Account expires:账户过期日期,never表示永不过期。
  • Minimum number of days between password change:两次修改之间的最小间隔。
  • Maximum number of days between password change:最大有效天数。
  • Number of days of warning before password expires:过期前提醒天数。

这个命令的优点是直观,不需要你手动做日期加减,非常适合日常巡检。需要注意的是,chage -l在部分较老系统上对普通用户可能不允许执行,需要 root 权限才能查看其他用户的完整信息。

2.2 passwd -S 适合快速判断状态

有时候你只想知道这个用户的密码是不是要过期了,其他信息暂时不重要,这时候passwd -Schage -l更直接。

passwd -S zhangsan

输出可能是这样的:

zhangsan PS 2024-01-05 90 7 30

字段含义从左到右依次是:用户名、密码状态、上次修改日期、最大有效天数、提醒天数、宽限天数。

密码状态那一列有几个关键值需要记住:

  • PS:password set,密码已设置,正常状态。
  • LK:locked,密码被锁定,用户无法登录。
  • NP:no password,没有设置密码,常见于一些只允许密钥登录的系统账户。

如果只想看密码状态,不关心具体日期,这个命令的效率比chage高。我习惯在写巡检脚本时用它做第一轮扫描,命中异常用户后,再用chage -l看详细时间线。

2.3 直接读 /etc/shadow,手动解析也不难

虽然chage -l已经足够方便,但了解手动解析/etc/shadow依然有其价值。原因有两个:一是在某些精简环境中,可能没有安装chage工具;二是在批量处理脚本中,直接提取字段往往更快。

读取某个用户的 shadow 记录:

grep '^zhangsan:' /etc/shadow

得到的第 3、5、8 字段就是核心信息。这里需要用到一个小技巧:把天数换算成日期。Linux 系统的参考日期是 1970 年 1 月 1 日,可以用date命令做转换。

例如,将19000天换算成日期:

date -d "1970-01-01 + 19000 days" "+%Y-%m-%d"

输出:

2022-01-06

如果熟悉这层换算关系,你在日志或告警里看到一串数字时,也能迅速判断用户的密码是否即将过期。我见过不少新人,在告警系统里收到“shadow line 3 is 19000”这样的消息后一脸茫然,其实就是这么个换算而已。

3. 修改密码过期时间与账号策略:chage 命令实战

3.1 chage 常用参数拆解与场景

修改密码过期时间的核心命令同样是chage,只是把查看参数换成修改参数。我按日常使用频率整理了一张速查表:

参数作用示例
-M设置密码最大有效天数,即密码过期周期chage -M 90 zhangsan
-m设置两次修改密码的最小间隔天数chage -m 5 zhangsan
-W设置过期前警告天数chage -W 7 zhangsan
-I设置过期后的宽限天数,超过则禁用chage -I 30 zhangsan
-E设置账户绝对过期日期,可使用YYYY-MM-DDchage -E 2024-12-31 zhangsan
-d修改“最后一次修改日期”,通常用于重置密码周期chage -d 2024-01-01 zhangsan

其中-M是重点中的重点。比如希望用户的密码 90 天过期一次:

chage -M 90 zhangsan

如果要取消密码过期,让它永不过期,则可以把天数设为-1

chage -M -1 zhangsan

为什么是-1而不是 0?因为 0 代表“下次登录必须立刻改密码”,这是另一个完全不同的语义。用-1或者99999都是历史遗留的常用写法,现代系统里-1更规范。这里的区别一定要记清楚,否则你本想取消过期限制,结果会让所有用户一登录就被强制改密码。

-E参数用于账户的绝对过期,比如临时外包人员只允许工作到年底:

chage -E 2024-12-31 tempuser

执行后,当天 00:00 过后该用户就无法登录了,不管密码是否有效。取消账户过期则设-E -1

3.2 场景实操:新建用户的密码策略配置

新建用户时顺便把密码策略一起配上,是运维里最推荐的做法,省得后面反复调整。假设现在要为一名新员工创建用户lisi,要求密码 90 天过期,过期前 7 天提醒,密码最小修改间隔为 5 天。

完整操作序列如下:

useradd lisi passwd lisi chage -M 90 -m 5 -W 7 lisi

第三条命令把三个策略一次性设置好,是不是很整洁?注意chage支持多个参数同时使用,不用一条条执行。

还有一种常见需求:用户第一次登录时必须修改密码。这个操作看起来像是“密码过期”,但实际用的是-d 0,它把“最后一次修改日期”设为 0,表示从未修改过密码:

chage -d 0 lisi

这样用户首次登录时就会被要求重新设置密码。这个操作特别适合账号开通场景,初始密码只有管理员知道,用户登录后必须改成自己的密码。

如果后续发现某个用户的密码有效期太长或太短,也可以用同样的方式快速调整。比如研发部希望密码半年换一次:

chage -M 180 -m 7 -W 14 devuser

3.3 批量修改与脚本化操作

服务器多了以后,逐台、逐用户执行chage肯定不现实。批量修改的方式主要有两种:第一种是写 for 循环脚本;第二种是使用配置管理工具如 Ansible、SaltStack。

先看一个简单的 for 循环脚本,它能对多个用户名批量设置密码策略:

for user in zhangsan lisi wangwu; do chage -M 90 -m 5 -W 7 "$user" chage -l "$user" | head -5 done

脚本里边的chage -l是用来输出验证的,确认每个用户的策略都改成功了。习惯上,批量操作前建议先导出当前用户的策略,方便回滚:

for user in $(cat userlist.txt); do echo "=== $user ===" >> policy_backup.txt chage -l "$user" >> policy_backup.txt done

如果你管理的机器上有 Ansible,操作会更方便,直接对一批机器下发配置:

- name: Set password expiration policy ansible.builtin.shell: chage -M 90 -m 5 -W 7 {{ item }} loop: "{{ users }}"

不管用哪种方式,我建议在批量修改之前先在一个测试用户上试跑,确认策略影响面,再推向生产环境。这看起来是常识,但我试过在实际操作中因为写错用户名,把策略应用到了错误账户上,最后排查了半天才锁定问题。批量操作尤其要小心。

4. 常见问题与排查技巧实录

4.1 密码过期前有没有提醒机制?

有,但要区分“系统登录时的提醒”和“主动发送到邮箱或短信的提醒”。

系统登录时的提醒,主要靠的是chage -W设定的警告天数。当用户在警告期内尝试登录时,终端上会显示类似如下信息:

Warning: your password will expire in 5 days

这个提醒对 SSH 登录和本地终端都有效,但对使用图形界面或 WinSCP 等工具登录的用户,提示效果可能不那么明显,因为部分工具会直接弹出密码过期窗口,或者干脆忽略警告。

如果想做到主动通知,比如提前一周把“密码即将过期”的邮件发给用户,那就得额外配置脚本了。常见做法是在 cron 里写一个巡检脚本,每天扫描/etc/shadow或使用chage -l判断哪些用户的密码即将到期,然后利用mail命令发送通知。这个流程做起来不难,但很多公司并没有部署,导致用户经常“被动过期”,然后才来找运维重置密码。

4.2 为什么改了 /etc/shadow 里的日期没生效?

这是我在答疑时被问到最多的问题之一。不少人会直接 vi 编辑/etc/shadow,把第 5 个字段从 90 改成 180。保存后执行chage -l查看,发现显示的日期还是旧的,甚至会提示格式错误。

原因在于/etc/shadow文件里的日期字段是“天数”,不是“YYYY-MM-DD”。你直接在文件里写2024-04-01,程序会把它当成一个天数值去计算,结果自然就错了。比如 2024 在日期换算里代表从 1970 年起的第 2024 天,也就是 1975 年,这显然不是你要的效果。

所以操作上要分清楚:如果要直接改文件,数字必须是从 1970 年算起的天数;如果觉得换算麻烦,就老老实实用chage命令,让它帮你处理。除非你是写自动化脚本,否则不建议手动编辑/etc/shadow,一不小心改错一个字段,可能导致用户彻底无法登录。

4.3 用户密码过期后怎么临时救急?

用户密码过期、远程又登不上时,最直接的办法是让用户联系管理员重置密码。管理员执行下面两条命令之一即可:

passwd zhangsan

或者如果你想顺手把密码过期策略清掉,可以执行:

chage -M 99999 zhangsan passwd zhangsan

第一条命令把密码有效期改成 99999 天,基本等于永不过期;第二条命令重置密码。重置后用户的密码状态会重新开始计算。

如果你判断用户只是密码过期,并且不想强制它改密码,可以手动把最后修改日期设置为今天,这样密码周期重新开始:

chage -d $(date +%Y-%m-%d) zhangsan

这里用date +%Y-%m-%d动态取当前日期,比较省事。实测下来这个命令在多数发行版上都能正常工作,个别老系统对日期格式要求严格,建议用YYYY-MM-DD格式。

4.4 过期时间边界:第几天锁定,第几天失效?

很多人以为密码过期当天就登录不上去了,其实不是。密码过期后用户还能登录,但系统会立即要求修改密码。如果用户不修改,等到“宽限期”也过了,账户才会被锁定。

举个例子,假设密码最大有效天数为 90 天,宽限天数为 30 天:

  • 第 1 天到第 83 天:正常登录,无提示。
  • 第 84 天到第 90 天:登录时出现警告,提示密码即将过期。
  • 第 91 天到第 120 天:密码已过期,用户必须修改密码才能继续使用系统。
  • 第 121 天开始:宽限期结束,账户被系统禁用,只能管理员干预。

宽限期的天数由/etc/shadow第 7 个字段控制,对应chage -I参数。合理设置这个值很重要,设太短,用户出差一周回来就可能进不去;设太长,密码长期不更新,安全风险又高。一般建议 7 到 30 天。

我在实际使用中发现,很多发行版默认的宽限天数是空值或 0,也就是说密码过期当天不修改,账户就直接锁死。如果你管理的用户经常出差、远程办公,最好提前把所有账号的宽限期统一改成 15 天或 30 天,能省掉不少半夜救急的麻烦。

另外还有个细节:如果用户密码已被设置成“永不过期”的-1状态,但-I(宽限期)依然有值,那么宽限期并不会生效,因为系统认为密码永远不会过期,自然也不需要宽限。这个逻辑要理解清楚,不要在前面设置-M -1后又因为-I配置而困惑为什么没有锁定动作。

最后说说 root 账户。对 root 设置密码过期策略要格外谨慎。一旦 root 密码过期,而你又没有其他可用的 sudo 用户或物理控制台权限,可能连系统都进不去,只能通过单用户模式或救援盘处理。所以生产环境上,root 的密码过期策略我通常保持默认不设限制,或者设置一个非常长的期限,同时对 root 密码本身做严格管理,比如只在特定维护窗口使用,使用后立即通过带外管理修改。

做运维这些年,我最大的感受是:密码过期机制本身不复杂,复杂的是它和人的行为耦合在一起。用户不会按照你定的 90 天周期自觉改密码,也不会因为警告信息醒目就提前处理。真正靠谱的做法是把查看过期时间、批量调整策略、提前发送提醒这三件事串成一套自动化流程,而不是等用户找上门才想起自己会几条chage命令。把本文里的命令都实际敲一遍,再写两个小脚本,这套技能基本就长在你身上了。

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

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

立即咨询