| Tested on | RHEL 10.2 (Coughlan) |
|---|---|
| Package | shadow-utils 4.15.0-11.el10 |
| Applies to | RHEL, Rocky Linux, AlmaLinux, Fedora, Debian, Ubuntu, and other Linux distributions with shadow password support |
| Privilege | sudo or root to inspect other users; users can run chage -l on their own account |
| Scope | Read last password change, expiration, and status for local Linux accounts with chage, passwd -S, and /etc/shadow. Does not cover setting password-aging policy or checking AD/LDAP password expiry from Linux. |
| Related guides | chage command Implement password policy in RHEL Add user to group in Linux sudo command |
To see when a local user's password was last changed and when it expires, run chage -l USERNAME. Last password change is the date recorded in /etc/shadow. Password expires is derived from the last-change date and maximum password age; when password aging is disabled or unlimited, it is shown as never. Account expires is a separate calendar limit on the account itself.
Quick reference: password age and expiration commands
| Task | Command |
|---|---|
| Check all aging information | sudo chage -l USER |
| Use ISO dates | sudo chage -i -l USER |
| Check password status | sudo passwd -S USER |
| Check status for all local users | sudo passwd -S -a |
| Read shadow entry | sudo getent shadow USER |
| Grep shadow file | sudo grep '^USER:' /etc/shadow |
Check last password change with chage
chage -l lists every aging field for a local account from /etc/shadow.
sudo chage -l pwcheckSample output:
Last password change : Aug 16, 2026
Password expires : Nov 14, 2026
Password inactive : never
Account expires : never
Minimum number of days between password change : 0
Maximum number of days between password change : 90
Number of days of warning before password expires : 7The Last password change line is what most administrators need. Locale-specific month names can make scripting awkward, so use ISO dates when you plan to parse the output:
sudo chage -i -l pwcheckSample output:
Last password change : 2026-08-16
Password expires : 2026-11-14
Password inactive : never
Account expires : never
Minimum number of days between password change : 0
Maximum number of days between password change : 90
Number of days of warning before password expires : 7Do not rely on chage -l USER | head -1 as a shortcut. The full chage -l output already includes expiration, inactivity, and account-expiry lines you need in the next section.
Check when a password expires
Read the same chage -l output and focus on four lines:
- Last password change — date the stored password hash was last updated
- Password expires — derived from last-change date and maximum password age (
-Mpolicy); shown asneverwhen aging is disabled or unlimited - Password inactive — date when the post-expiry inactivity period ends; the underlying inactivity setting is a number of days after password expiration
- Account expires — calendar date when the account itself is disabled, independent of the password
These settings are easy to confuse:
Password expiration is controlled by maximum password age. After the password expires, the user is required to change it before continuing to use the account.
Password inactivity is the grace period after password expiration. Once that period also expires, the user can no longer log in with the expired password and administrator intervention may be required. The chage -I option sets the number of days for this grace period.
Account expiration disables the account on a fixed date regardless of password age.
To change maximum age, warning days, or account expiry, see the chage command guide. This article focuses on reading current values.
Check password status with passwd -S
passwd -S prints a one-line summary: status code, last change, and aging numbers.
sudo passwd -S pwcheckSample output:
pwcheck P 2026-08-16 0 90 7 -1The seven fields are username, status, last change, minimum age, maximum age, warning period, and inactivity period.
Current shadow-utils status codes:
P— usable passwordL— locked passwordNP— no password
A locked system account shows L in the status column. On the lab host, bin is an example:
sudo passwd -S binSample output:
bin L 2025-04-08 0 99999 7 -1The third field matches the Last password change date from chage -l for the same user.
Check password expiration for all local users
List every local account in one pass:
sudo passwd -S -aSample output (trimmed):
root P 2026-08-03 0 99999 7 -1
bin L 2025-04-08 0 99999 7 -1
pwcheck P 2026-08-16 0 90 7 -1Each line gives status and aging numbers but not the human-readable Password expires date. When you need that detail for several users, loop chage -i -l over accounts listed in /etc/passwd:
for u in $(cut -d: -f1 /etc/passwd); do
echo "=== $u ==="
sudo chage -i -l "$u" 2>/dev/null | grep -E '^(Last password change|Password expires)'
doneCheck last password change in /etc/shadow
The third colon-separated field in /etc/shadow stores the last password change as a day count since 1970-01-01.
sudo grep '^pwcheck:' /etc/shadowSample output (hash trimmed):
pwcheck:$y$j9T$YPIWaN6XoDLI1FgCySgko0$I.iyvFIfpwyZFC7UzgH5B2Ka0F2swsWhyr.zXtqs.m4:20681:0:90:7:::Field 3 (20681 here) is the last-change counter:
username:hash:LAST_CHANGE:min:max:warn:inact:expire:reserved
^
last password change (days since 1970-01-01)Convert that counter to a calendar date when you are reading shadow directly:
date -d '1970-01-01 +20681 days' +%Y-%m-%dSample output:
2026-08-16For day-to-day checks, chage -l or chage -i -l is easier than decoding shadow fields by hand.
Can Linux show the exact password change time?
No — not from shadow data alone. /etc/shadow records last change as a day number, not a timestamp. chage, passwd -S, and a decoded shadow field therefore report the date, not the hour, minute, or second.
If auditd or journald captured the original passwd or chage event, those logs may include a precise timestamp. That is separate historical logging and may no longer exist after rotation or on hosts without auditing enabled.
Why the recorded last-change date can be modified
chage, passwd -S, and /etc/shadow report the account's current stored last-change value. A privileged administrator can change that field without changing the password hash:
sudo chage -d 2026-08-10 pwcheckAfter that command, chage -i -l shows the new date:
sudo chage -i -l pwcheck | head -1Sample output:
Last password change : 2026-08-10That update does not prove the password itself was changed on that day. When you need historical evidence of password-change events, check audit or journal records if your site collects them — not the shadow field alone.
Local users vs LDAP and Active Directory users
chage reads local shadow password information. It does not report password-aging policy obtained from external identity providers such as LDAP or Active Directory.
If a user authenticates through SSSD or another NSS source and has no local /etc/shadow entry, chage -l may fail or show nothing useful. Check password expiry on the directory server or through your identity stack instead. Joining Linux to AD is covered in join Linux to a Windows domain; AD password expiry from Linux deserves its own focused guide.
References
- Linux
chage(1)manual — https://man7.org/linux/man-pages/man1/chage.1.html - Linux
passwd(1)manual — https://man7.org/linux/man-pages/man1/passwd.1.html - Linux
shadow(5)manual — https://man7.org/linux/man-pages/man5/shadow.5.html
Summary
To check last password change and expiration on a local Linux account, start with sudo chage -l USERNAME. Add -i when you want ISO dates for scripts. The Last password change line comes from /etc/shadow; Password expires is derived from that date and maximum password age, or shows never when aging is unlimited; Account expires is a separate account-level limit.
sudo passwd -S USER gives a compact status line with current P, L, or NP codes. Use sudo passwd -S -a to scan every local user quickly, then chage -i -l when you need full expiry dates. Shadow field 3 holds the same last-change counter if you are already reading /etc/shadow directly.
Shadow data stores a date, not a clock time, and root can rewrite the last-change field with chage -d without changing the password. Treat chage and passwd -S as the authoritative current record for local accounts, and use directory tools for LDAP or AD users. To set aging policy, open the chage command guide instead of this page.

