Just by checking through my own syslog I can see that cron jobs usuallY start 1 second past the minute (Ubuntu 20.04). (Eg: ten past five triggers at 05:10:01
). On my system this is pretty stable, but I wouldn't garentee it.
Under heavy load this might be worse because even if the cronjob triggered at the right time, extremely heavy load could delay excve for more than a second. But then such extreme load would slow your script down so much the start time would become largely meaningless.
Cron can and does occasionally skip jobs, for example if the system is switched off it will never catch up. I would be especially careful of this note in the manual:
Note that this means that non-existent times, such as "missing hours" during daylight savings conversion, will never match, causing jobs scheduled during the "missing times" not to be run. Similarly, times that occur more than once (again, during daylight savings conversion) will cause matching jobs to be run twice.
Make sure your code won't break if it runs at 05:10:02 instead of 05:10:01.
There's no elegant way to get cron to tell you which job is running. You can setup many identical jobs to run at different times, each job could pass in the time as an argument. I see two options:
Setup a crontab with many entries
Do check the notes below.
Yes there's 1440 minutes in a day, so if you need a crontab to run this minutely you might need a script to generate your crontab:
#!/bin/bash
for hour in {0..23} ; do
for minute in {0..59} ; do
echo "${minute} ${hour} * * * root /path/to/script.sh ${hour}:${minute}:01"
done
done > /etc/cron.d/my-job
You'll end up with something like this:
01 00 * * * root my-job 00:01:01
02 00 * * * root my-job 00:02:01
03 00 * * * root my-job 00:03:01
...
Create a wrapper script to find the nearest expected run
It might be better to create a wrapper script which checks the current time and finds the nearest entry. If your job is set to run every 15 minutes you could use the example provided here:
#!/bin/bash
curdate=`date "+%s"`
run_time=$(($curdate - ($curdate % (15 * 60))))
run_time_arg=$(date -d"@$run_time" "+%H:%M:%S")
/path/to/script.sh $run_time_arg
Note this does use behaviour specfic to GNU date
and may not work on all implementations
hh:mm:00
. I'm not sure how many concurrent jobs you would have to run to have one of them take more than 59 seconds to start. You could run this job every minute for a week:* * * * * date >> ~/cron.tester
and do the statistics on the :SS field. Perhaps running a script to run the date would be a more realistic scenario, though.