Running a PHP script every 5 minutes and avoiding race conditions

后端 未结 5 1281
无人及你
无人及你 2021-01-12 12:13

I have a php script that needs to run once every 5 minutes. Currently I\'m using a cron job to run it (and it works great) but my host only allows a minimum time of 15 minut

相关标签:
5条回答
  • 2021-01-12 12:23

    The answer to whether visitors can start this script is yes. You can run the script when visitors enter a page. You would want to store start time, but also an attribute for whether it is running. This should avoid any possibility of conflict when trying to update your data. I'de also put an additional field for mail warning which you can use if the runtime passes what you would expect as beyond max time. You can then have the script send you a warning email that your script have been running beyond max time. I've personally kept these statuses in databases, but they can also be stored in files.

    0 讨论(0)
  • 2021-01-12 12:24

    Lame answer for a lame situation (the ISP, not the poster). Schedule 12 cron jobs, all calling the same script, each running once per hour, but calling at a different 5 minute mark.

    00 * * * * root echo "run at :00 of every hour"
    05 * * * * root echo "run at :05 of every hour"
    10 * * * * root echo "run at :10 of every hour"
    

    etc until :55. But I stand by my original comment - find a new ISP :)

    0 讨论(0)
  • 2021-01-12 12:29

    Have you considered just having your script run an infinite loop with a sleep to wait 5 minutes between iterations?

    for (;;)
    {
      perform_actions();
      sleep(300);
    }
    

    Alternatively, you could have a file (for example, is_running), and get an exclusive lock on it at the start of your script which is released at the end. At least this way you will not do anything destructive.

    You could also combine these two solutions.

    $fp = fopen("is_running", "r+");
    
    /* is it already running? */
    if (! flock($fp, LOCK_EX | LOCK_NB)) return;
    
    for (;;)
    {
      perform_actions();
      sleep(300);
    }
    

    And then have the cron job still run every 15 minutes. If the process is still running, it will just bail out, otherwise it will relaunch and resume updating every 5 minutes.

    0 讨论(0)
  • 2021-01-12 12:33

    If you cannot do what @Brandon suggested, I would recommend the approaching this in the same way I did when writing a daemon in PHP (not the best solution but I was practically forced to do this).

    In my case as well the script accessed a (log)file and did processing on it, afterwards inserting the results in the database. So to ensure that I don't have two files running at the same time, I created a "status" file on which the script acquired a lock and if not able to do so if failed gracefully.

    $fh = fopen('status_file', 'w');
    
    /**
     * LOCK_NB is required because otherwise your script would stall until
     * a lock is aquired, queing a bunch of scripts.
     */
    if(!flock($fh, LOCK_EX | LOCK_NB)) {
      exit 1; // our job is done here
    }
    
    0 讨论(0)
  • 2021-01-12 12:34

    You can use The Fat Controller to run a script at 5 minute intervals. Unlike CRON it guarantees the interval from when one instance of the script ends to when another one is started.

    0 讨论(0)
提交回复
热议问题