必须用pam_exec.so在登录会话建立后立即执行脚本输出高亮警告,而非仅依赖chage -w;需确保warn字段生效、脚本权限正确、path精简兼容、selinux策略适配,并严格校验剩余天数。

直接生效的终端警告提醒,必须靠 pam_exec.so 在登录会话建立后立即执行脚本输出,不能只依赖 chage -W 设置的默认提示——那个提示太弱,常被启动日志淹没,且只在密码认证阶段出现一次,用户可能根本没看到。
确认 chage -W 已正确写入 /etc/shadow 的 warn 字段
这是整个提醒链的起点。如果 warn 值没生效,后续脚本读不到有效剩余天数:
- 运行
sudo chage -W 7 username(别用 0 或负数) - 检查输出:
sudo chage -l username,确认 “Password expires” 和 “Warning before password expires” 两行都显示非空值 - 新建用户要同步检查
/etc/login.defs中的PASS_WARN_AGE是否为 7;否则新用户 shadow 里 warn 字段是空的
用 pam_exec.so 在 login/sshd 会话中插入高亮提示
默认的 PAM 提示不醒目、不可控。必须手动注入一个带 emoji 和空行的脚本,在用户拿到 shell 前强制刷屏:
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
- 编辑
/etc/pam.d/login(TTY)或/etc/pam.d/sshd(SSH),在末尾加一行:session optional pam_exec.so stdout /usr/local/bin/passwd-expiry-notice.sh - 脚本内容关键点:
— 必须用$PAM_USER获取当前登录用户名,不能硬编码
— 解析chage -l输出时用awk -F': ' '/Password expires/ {print $2}'避免字段错位
— 剩余天数必须用[[ "$remaining" =~ ^[0-9]+$ ]]严格校验,防止字符串误判 - 脚本示例片段:
#!/bin/bash days=$(chage -l "$PAM_USER" 2>/dev/null | awk -F': ' '/Password expires/ {print $2}' | xargs) [[ -z "$days" || "$days" == "never" ]] && exit 0 remaining=$(echo "$days" | awk '{print $1}') [[ "$remaining" =~ ^[0-9]+$ ]] && [ "$remaining" -le 7 ] && [ "$remaining" -gt 0 ] && { echo -e "\n⚠️ WARNING: Your password expires in ${remaining} day(s)!" echo "Please run 'passwd' now." echo "" }
避免常见失效场景
这个机制看似简单,但实际部署中 80% 的失败源于以下三点:
-
/usr/local/bin/passwd-expiry-notice.sh缺少+x权限,或路径拼错(注意不是/usr/bin) - 脚本里用了
date或bc等非基础命令——PAM session 环境 PATH 极其精简,只认/bin和/usr/bin下的命令 - 在 RHEL/CentOS 上改了
/etc/pam.d/sshd却忘了 SELinux 策略:需运行sudo setsebool -P ssh_sysadm_login on或打标签sudo semanage fcontext -a -t bin_t "/usr/local/bin/passwd-expiry-notice.sh"
真正可靠的提醒,不是“系统说了”,而是“用户一眼看见、无法忽略、且每次登录都重复出现”。脚本输出里的空行和 ⚠️ 符号不是装饰,是防止被滚动日志吞掉的最后防线。别省略它们。










