Don’t run script if it’s already running

I’ve been completely unsuccessful finding an answer to this question. Hopefully someone here can help.

I have a PHP script (a WordPress template, to be specific) that automatically imports and processes images when a user hits it. The problem is that the image processing takes up a lot of memory, particularly if multiple users are accessing the template at the same time and initiating the image processing. My server crashed multiple times because of this.

Read More

My solution to this was to not execute the image-processing function if it was already running. Before the function started running, I would check a database entry named image_import_running to see if it was set to false. If it was, the function then ran. The very first thing the function did was set image_import_running to true. Then, after it was all finished, I set it back to false.

It worked great — in theory. The site hasn’t crashed since, I can tell you that. But there are two major problems with it:

  1. If the user closes the page while it’s loading, the script never finishes processing the images and therefore never sets image_import_running back to false. The template will never process images again until it’s manually set to false.

  2. If the script times out while it’s processing images — and that’s a strong possibility if there are many images in the queue — you have essentially the same problem as No. 1: the script never gets to the point where it sets image_import_running back to false.

To handle No. 1 (the first one of the two problems I realized), I added ignore_user_abort(true) to the script. Did it work? I don’t know, because No. 2 is still an issue. That’s where I’m stumped.

If I could ask the server whether the script was running or not, I could do something like this:

if($import_running && $script_not_running) {
    $import_running = false;
}

But how do I set that $script_not_running variable? Beats me.

I’ve shared this entire story with you just in case you have some other brilliant solution.

Related posts

Leave a Reply

7 comments

  1. Try using
    ignore_user_abort(true); it will continue to run even if the person leaves and closes the browser.

    you might also want to put a number instead of true false in the db record and set a maximum number of processes that can run together

  2. As others have suggested, it would be best to move the image processing out of the request itself.

    As an interim “fix”, store a timestamp alongside image_import_running when a processing job begins (e.g., image_import_commenced). This is a very crude mechanism, but if you know the maximum time that a job can run before timing out, the script can check whether that period of time has elapsed.

    e.g., if image_import_running is still true but the current time is more than 10 minutes since image_import_commenced, run the processing anyway.

  3. What about setting a transient with an expiry time that would throttle the operation?

    if(!get_transient( 'import_running' )) {
      set_transient( 'import_running', true, 30 ); // set a 30 second transient on the import.
      run_the_import_function();
    }
    
  4. For Me i use just this simple idea with a text document. for example run.txt file
    in the top script use :

    if((file_get_contents('run.txt') != 'run'){ // here the script will work
    $file = fopen('run.txt', 'w+');
    fwrite($file, 'run');
    fclose('run.txt');
    }else{
    exit(); // if it find 'run' in run.txt the script will stop
    }
    

    And add this in the end of your script file

    $file = fopen('run.txt', 'w+');
    fwrite($file, ''); //will delete run word for the next try ;)
    fclose('run.txt');
    

    That will check if script already work by checking runt.txt contents
    if run word exist in run.txt it will not run

  5. Just add following on the top of your script.

    <?php
        // Ensures single instance of script run at a time.
        $fileName = basename(__FILE__);
        $output = shell_exec("ps -ef | grep -v grep | grep $fileName | wc -l");
        //echo $output; 
        if ($output > 2)
        {
            echo "Already running - $fileNamen";
            exit;   
        }
    
        // Your php script code.
    ?>