1

sorry if this question has been asked before, however I could not find anything relevant when searching.

I currently have a PHP script which polls a database for the next record which is has not been updated. My question is this: If I then update the database to show that the record is processing while the cron job is running (which takes approx 30 seconds), and the cron job is set to run every second, at second 1 the cron job runs, but will this job wait to complete before the cron job runs for the second time, or will it run at second 2?

Thanks

Mike Bowyer
  • 11
  • 1
  • 2
  • Surely the minimum time for a cron schedule is one minute? – Mark Baker Sep 21 '15 at 16:37
  • And no, cron jobs will run at their schedule, and if they overlap then it's up to your code to handle things, cron doesn't care if a previous job is still running – Mark Baker Sep 21 '15 at 16:38
  • There might be a better way to accomplish what I am trying to do then - I am building a system which will have multiple users, each with an online sales channel attached, e.g. Amazon. I need to be able to constantly poll for orders for each of the accounts, ideally at the same time, however if one of the accounts has a large amount of orders and takes in excess of a minute to return all the pages of data in my script, I don't want all the other accounts stopped polling whilst the orders for that one account are downloaded, if that makes sense? – Mike Bowyer Sep 21 '15 at 17:00
  • Not a problem, arrange for the cron job to 'select, for update, of the next available 'order'. Mark it as being processed and commit it to the database. Then process the order. The next `cron job` will find a new order or nothing. – Ryan Vincent Sep 21 '15 at 17:03
  • Yeah that's what I was thinking about doing, so each account would be pending, then processing, then complete, so the first time it ran it would find user 1 as pending, and change it to processing. the second time it would find user 2 as pending because user 1 is currently processing, etc. – Mike Bowyer Sep 21 '15 at 17:06
  • Yes, that is exactly the states it goes through. I would add an 'error' state as well as 'completed'. But, yes, that will work. If done correctly, the `error` ones can be corrected and just set to a 'pending' state, to be reprocessed. – Ryan Vincent Sep 21 '15 at 17:08
  • Great thanks for your help Ryan – Mike Bowyer Sep 21 '15 at 17:14

3 Answers3

1

If you are using cronjob and not using any kind of locking in your php script the cron will run more than one copy of the script if the time event occurs before the last script finished.

To avoid such issue you can do something like this:

$LOCK_FN = "/tmp/my-script.lock"
if(file_exists ($LOCK_FN)){
    //previous script is not finish exit.
    die("Previous script is not finished yet.");
}
//Create lock
$fp = fopen($LOCK_FN,"w");
fclose($fp);

/*

 Put your script logic here
 */

//Open the lock work is done.
unlink($LOCK_FN)
  • Ok great thanks, so if the second cron job runs before the first cron job finishes, I am presuming it wont abort the first cron job? (This is actually what I want to happen, I need it to continuously process the next record even if the previous record hasn't finished). – Mike Bowyer Sep 21 '15 at 16:57
  • 1
    @MikeBowyer It may or may not affect the first job depending upon the type of processing and logic you wrote in your script; but it will be a bad bad idea to you your code that way; I highly recommend you to go with locking. –  Sep 21 '15 at 17:26
  • There is a big issue with locking, if for any reason the script crashed or server restarted while script is running, the cron job will never run again until you manually remove the lock file – Nawwar Elnarsh May 11 '17 at 12:16
1

Use sockets to lock something. Because if script gets terminated, the socket port is automatically open again.

<?php
$port = 1080; // choose unused port
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if (!$sock) {
    exit;
}
socket_set_nonblock($sock);
if (!socket_bind($sock, "127.0.0.1", $port)) {
    exit;
}

while(1) { ... }
?>

Use a different port per script.

Add this script to Crontab with * * * * *

Stefan
  • 305
  • 2
  • 10
0

The cronjob will not wait for the previous one to finish before launching a new instance. What you want is a daemon, see Run php script as daemon process

Community
  • 1
  • 1
Derek
  • 1,826
  • 18
  • 25