views:

118

answers:

3

I cannot set cron time to less than 1 minute even on my dedicated server. I need it to run every 15 seconds because it calls betfair api and calculations are highly time dependent. Please advise.

A: 

Cron only lets you run things as fast as once a minute.

What I would do is do the 15 second timings inside your script.

  • Execute a parent script once a minute.
  • Execute children scripts every 15 seconds within that script before it exists and a new cycle begins.
thomasmalt
Thanks.Please can you elaborate
Imran Naqvi
Thanks bro, after reading a lot i think your solutions is simplest and perfect.
Imran Naqvi
No its not. Part of the reason that cron only allows you to schedule to the nearest minute is that it provides no guarantees of when the job will actually start - so you get a large amount of jitter even at one minute. Having said that any sort of non-interactive processing should be a last resort on a web application. And if you need this kind of realtime scheduling accuracy then you should not be writing it in PHP. And possibly not even running it on something which is not a real-time OS.
symcbean
@symcbean You're right, of course, but with a proper amount of pragmatism applied, it will work satisfactory in most use cases. Personally I found @Lie Ryan's answer the most suitable, together with @Vegard Larsen's comment.
thomasmalt
thanks @symcbean so any other reliable solution.
Imran Naqvi
@symcbean, my application is so much dependent on minimum amount of time between two executions that i am planing to decrease 15sec to 5sec. That is why i moved to dedicated hosting. By the way i am running only and only this single script. Server details are OS:Ubuntu Linux 10.04.1, CPU: Intel(R) Core(TM)2 Duo CPU E7500 @ 2.93GHz 2 cores, RAM: 2GB.
Imran Naqvi
Given that I still think the right way to solve the problem is to redsign the application so that it doesn't need any batch processing, if this is not a viable solution then the only solution is to use a different (probably dedicated, bespoke) scheduling engine.
symcbean
+3  A: 

If you need to call a job every 15 second, don't use cron. cron is designed for requesting jobs to be done much later.

Instead, after the parent finishes the job, sleep for 15 seconds then call the child script, then exits. The child script can do its job, sleep for 15 second then call the next script. Lather, Rinse, Repeat.

If your server doesn't have time limit, then you don't even need to spawn a child script. Just sleep ever 15 seconds, do your thing, sleep 15 second, do the next thing, and so on. A sleeping script doesn't consume CPU, though it do consume RAM. But that's better than cycling your host's PID; which might cause your host to go uneasy.

Lie Ryan
I like how this sounds.
Elzo Valugi
Make sure you also set up some redundancy here. If your script should fail (because it will, eventually), make sure it is restarted by a cron job every minute if it is not already running. At most you'd loose a minute worth of data.
Vegard Larsen
Thanks for response. Also a good solution but i am not confident how my server will perform. I think it is best to run cron after 1min and sleep for 15 seconds.
Imran Naqvi
A: 

Cron is a job scheduler that is built to have a minimum one-minute resolution. If you need a finer resolution than that, you either have to find another scheduling tool or roll your own.

One I've used in the past is as follows. You configure a desired gap and a minimum gap and the following script will execute your payload every N seconds. Note that this is not a simplistic "wait N seconds between each iteration" scheduler. It actually starts the next iteration N seconds after the start of the previous one, not after the end.

The minimum gap is there so that, if your payload takes more than N seconds, it's not running it continuously. If you do want it to run continuously in that situation, just set the minimum gap to 0.

The code to do it is here:

#!/usr/bin/bash

payload() {
        if [[ $1 -eq 1 ]] ; then
                echo "Sleeping for  1 second  at $(date +%H:%M:%S)."
        else
                if [[ $1 -lt 10 ]] ; then
                        echo "Sleeping for  $1 seconds at $(date +%H:%M:%S)."
                else
                        echo "Sleeping for $1 seconds at $(date +%H:%M:%S)."
                fi
        fi
        sleep $1
        echo "               Finished at $(date +%H:%M:%S)."
        echo
}

gap=10
mingap=3
for i in {1..20} ; do
        next=$(($(date +%s) + ${gap}))
        payload ${i}
        if [[ ${mingap} -ne 0 ]] ; then
                sleep ${mingap}
        fi
        while [[ $(date +%s) -lt ${next} ]] ; do
                sleep 1
        done
done

The payload isn't part of the logic, it's just something I have there for debug purposes. You can replace that with whatever you want. In addition, the for loop is also a sample. You can replace it with an infinite loop or have the script only do (for example) 60 minutes of iterations with a new instance of the script being kicked off by cron each hour.

The sample run follows. You can see that the payload runs every ten seconds (with the odd eleven seconds due to the vagaries of sleep) up until it takes more than seven seconds to do it. At that point, the minimum gap kicks in.

Sleeping for  1 second  at 14:36:08.
               Finished at 14:36:09.

Sleeping for  2 seconds at 14:36:18.
               Finished at 14:36:20.

Sleeping for  3 seconds at 14:36:28.
               Finished at 14:36:31.

Sleeping for  4 seconds at 14:36:39.
               Finished at 14:36:43.

Sleeping for  5 seconds at 14:36:49.
               Finished at 14:36:54.

Sleeping for  6 seconds at 14:37:00.
               Finished at 14:37:06.

Sleeping for  7 seconds at 14:37:10.
               Finished at 14:37:17.

Sleeping for  8 seconds at 14:37:20.
               Finished at 14:37:28.

Sleeping for  9 seconds at 14:37:31.
               Finished at 14:37:41.

Sleeping for 10 seconds at 14:37:44.
               Finished at 14:37:54.

Sleeping for 11 seconds at 14:37:57.
               Finished at 14:38:08.

Sleeping for 12 seconds at 14:38:11.
               Finished at 14:38:23.

Sleeping for 13 seconds at 14:38:27.
               Finished at 14:38:40.

Sleeping for 14 seconds at 14:38:43.
               Finished at 14:38:57.

Sleeping for 15 seconds at 14:39:00.
               Finished at 14:39:15.

Sleeping for 16 seconds at 14:39:18.
               Finished at 14:39:34.

Sleeping for 17 seconds at 14:39:38.
               Finished at 14:39:55.

Sleeping for 18 seconds at 14:39:58.
               Finished at 14:40:16.

Sleeping for 19 seconds at 14:40:19.
               Finished at 14:40:38.

Sleeping for 20 seconds at 14:40:41.
               Finished at 14:41:02.
paxdiablo