A certificate is bought once, installed once, and the diary entry belongs to whoever did it — which survives about as long as their current job. Two years later it expires on a Saturday morning, and the first report is a customer’s screenshot of a full-page browser warning, which is a considerably worse failure than the site simply being down.
# check what is actually being served, not what is on disk
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null
| openssl x509 -noout -subject -issuer -dates
# notBefore=Oct 14 00:00:00 2013 GMT
# notAfter=Oct 14 23:59:59 2015 GMT
# exit non-zero inside 30 days: cron, or a monitoring check
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null
| openssl x509 -noout -checkend 2592000
|| echo 'example.com certificate expires within 30 days'
Checking what is served rather than the file on disk is the part that matters, because the two disagree more often than seems possible: a renewed certificate copied into place and never reloaded, a second server in the pool that was missed, an SNI virtual host still presenting the default. -checkend takes seconds and gives an exit code, so it drops into cron or a Nagios check with nothing to parse. Thirty days is the right window when renewal means buying something — the purchase, the CSR, a validation email to an address on a domain nobody reads any more, and the reissue can take a week between them. Give the intermediate chain its own alarm as well: it expires on its own schedule, desktop browsers paper over a missing one from cache and mobile clients do not, so a chain problem presents as “the site is broken on phones”.