Options
-w sets how many days of warning you want, 30 by default. The hosts are the remaining arguments, each with an optional :port. With no hosts the script prints usage and exits 2.
Loop over the hosts
A for loop handles each host in turn. Parameter expansion splits host:port: ${target%%:*} keeps what is before the colon and ${target##*:} keeps what is after. No colon means port 443.
Read the certificate
openssl s_client opens the connection. -servername sends the host name (SNI), which shared hosting needs to pick the right certificate. </dev/null closes the connection straight away and timeout 15 stops a dead host hanging the script. openssl x509 -noout -enddate prints the expiry date and cut -d= -f2 keeps just the date.
Work out the days
date -d ... +%s turns the date into seconds, and the difference divided by 86400 gives whole days. Each host gets an OK, WARN, EXPIRED or ERROR line.
Exit code
0 means every certificate is fine. 1 means at least one is expiring, expired or unreadable, so cron or a monitoring tool can alert you.
Note: it checks the expiry date only. It does not check that the certificate chain is trusted or that the name matches.