We use cron-jobs to control lab instruments once a minute in the lab. I noticed that specifying 'once a minute' to cron produces a start-time for the job with quite a bit of variability. Usually the job starts at 1s past the minute, but sometimes 2s. There's also a random delay of 20 ms to 50 ms (but sometimes up to 300 ms). This probably depends a lot on the hardware. So if we assume the cron-job starts 1s past the minute the worst error I saw in the test above is 1.3 seconds.
Here's a very simple synchronization idea: first ask for a time-stamp, then wait until we are at an inter-second boundary, then continue. This makes the cron-job continue at the inter-second boundary with a maximum error of 6 ms, a fair improvement over 1.3 seconds without any sync code.
dt1 = datetime.datetime.now() # time-stamp when cron decides to run us
usecs_to_go = 1e6-dt1.microsecond # we want to run at an inter-second boundary
secs_target = 5 # we want to run at 5 seconds past minute
secs_to_go = secs_target - dt1.second -1 # amount of waiting to do.
time.sleep( secs_to_go+ usecs_to_go/1.0e6 )
dt2 = datetime.datetime.now() # now we are synced!?
fn = '/home/user/my_cron_log.txt'
# write to logfile for later analysis.
with open(fn,'a+') as f:
f.write(str(dt1) +" %02d.%06d" % (dt1.second, dt1.microsecond) + ' run!\n')
f.write(str(dt2) +" %02d.%06d" % (dt2.second, dt2.microsecond) + ' sync!\n')
The way to enable this to run from crontab is to add something like this to crontab (use crontab -e):
# m h dom mon dow command
* * * * * /usr/bin/python /home/user/cron_sync.py
Where cron_sync.py is the name of the script above.
I'd be interested in hearing how this works on other hardware, or if there are some alternative solutions.