Time remaining for the next run
cron
doesn't know when a job is going to fire. All it does is every minute, go over all the crontab
entries and fire those that match "$(date '+%M %H %d %m %w')"
.
What you could do is generate all those timestamps for every minute from now to 49 hours from now (account for DST change), do the matching by hand (the tricky part) and report the first matching one.
Or you could use the croniter python
module:
python -c '
from croniter import croniter
from datetime import datetime
iter = croniter("3 9 * * *", datetime.now())
print iter.get_next(datetime)'
For the delay:
$ faketime 13:52:00 python -c '
from croniter import croniter
from datetime import datetime
d = datetime.now()
iter = croniter("30 9 * * *", d)
print iter.get_next(datetime) - d'
19:37:59.413956
Beware of potential bugs around DST changes though:
$ faketime '2015-03-28 01:01:00' python -c '
from croniter import croniter
from datetime import datetime
iter = croniter("1 1 * * *", datetime.now())
print iter.get_next(datetime)'
2015-03-29 02:01:00
$ FAKETIME_FMT=%s faketime -f 1445734799 date
Sun 25 Oct 01:59:59 BST 2015
$ FAKETIME_FMT=%s faketime -f 1445734799 python -c '
from croniter import croniter
from datetime import datetime
iter = croniter("1 1 * * *", datetime.now())
print iter.get_next(datetime)'
2015-10-25 01:01:00
$ FAKETIME_FMT=%s faketime -f 1445734799 python -c '
from croniter import croniter
from datetime import datetime
d = datetime.now()
iter = croniter("1 1 * * *", d)
print iter.get_next(datetime) - d'
-1 day, 23:01:01
cron
itself takes care of that by avoiding to run the job twice if the time has gone backward, or run skipped jobs after the shift if the time has gone forward.
As it happens the %T
format of the printf
builtin of the ksh93
shell does support crontab specifications as input.
$ ksh93 -c 'printf "%(%F %T)T\n" now "30 9 * * *"'
2017-11-07 17:06:41
2017-11-08 09:30:00
So you can get the delta in seconds there with:
#! /bin/ksh93
crontab_line='30 9 * * *'
delta=$(($(printf '(%(%s)T - %(%s)T) / 60' "$crontab_line" now)))
echo "Next run in $((delta/60)) hours and $((delta%60)) minutes."