Linux用户密码过期时间查看与修改:chage与/etc/shadow实战
做运维这行早晚会碰到一个尴尬的场面某个用户的密码过期了人又不在电脑前远程登录直接报“密码过期”SSH 都进不去。用户打电话来催你得在十分钟内搞清楚他密码是什么时候设的、什么时候过期、要不要改策略。这时候如果你只会重启服务器那用户可能就要“重启”你了。这篇文章专门讲 Linux 下如何查看和修改用户密码过期时间。覆盖面包括chage、passwd -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 -S比chage -l更直接。passwd -S zhangsan输出可能是这样的zhangsan PS 2024-01-05 90 7 30字段含义从左到右依次是用户名、密码状态、上次修改日期、最大有效天数、提醒天数、宽限天数。密码状态那一列有几个关键值需要记住PSpassword set密码已设置正常状态。LKlocked密码被锁定用户无法登录。NPno 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如果要取消密码过期让它永不过期则可以把天数设为-1chage -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 devuser3.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命令。把本文里的命令都实际敲一遍再写两个小脚本这套技能基本就长在你身上了。

相关新闻

Blackwell架构下SageAttention重构ComfyUI工作流

Blackwell架构下SageAttention重构ComfyUI工作流

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 12:31:23 阅读更多 →
POJ在线评测系统新手入门:从注册到第一个AC的完整指南

POJ在线评测系统新手入门:从注册到第一个AC的完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 12:31:23 阅读更多 →
120急救中心AI指挥调度平台建设方案:从语音转写到智能派车的四层架构与落地实践

120急救中心AI指挥调度平台建设方案:从语音转写到智能派车的四层架构与落地实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 12:31:23 阅读更多 →

最新新闻

Windows Update错误代码全解析:从0x800到0x803的分层排查与修复

Windows Update错误代码全解析:从0x800到0x803的分层排查与修复

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 13:12:55 阅读更多 →
OTN技术体系详解:从G.872架构到G.709帧结构与保护

OTN技术体系详解:从G.872架构到G.709帧结构与保护

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 13:12:55 阅读更多 →
Linux指令实战指南:从文件操作到Docker部署的高频命令详解

Linux指令实战指南:从文件操作到Docker部署的高频命令详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 13:12:54 阅读更多 →
云边协同实战指南:从架构设计到断网自治

云边协同实战指南:从架构设计到断网自治

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 13:12:54 阅读更多 →
SINUMERIK 840D SL PCU BASE IPC版开机调试全指南

SINUMERIK 840D SL PCU BASE IPC版开机调试全指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 13:12:54 阅读更多 →
FreeMaster Recorder:嵌入式实时变量采集与波形调试原理

FreeMaster Recorder:嵌入式实时变量采集与波形调试原理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 13:11:54 阅读更多 →

日新闻

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:19 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/24 0:00:19 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/23 4:55:02 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/23 9:53:41 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/23 9:53:40 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →