Php Don';如果脚本为';它已经在运行了

Php Don';如果脚本为';它已经在运行了,php,wordpress,Php,Wordpress,我一直没有找到这个问题的答案。希望这里有人能帮忙 我有一个PHP脚本(具体来说是WordPress模板),当用户点击它时,它会自动导入和处理图像。问题在于图像处理占用大量内存,特别是当多个用户同时访问模板并启动图像处理时。我的服务器因此多次崩溃 我的解决方案是,如果图像处理功能已经在运行,就不执行它。在函数开始运行之前,我会检查名为image\u import\u running的数据库条目,看看它是否设置为false。如果是,则函数将运行。函数所做的第一件事就是将image\u import\

我一直没有找到这个问题的答案。希望这里有人能帮忙

我有一个PHP脚本(具体来说是WordPress模板),当用户点击它时,它会自动导入和处理图像。问题在于图像处理占用大量内存,特别是当多个用户同时访问模板并启动图像处理时。我的服务器因此多次崩溃

我的解决方案是,如果图像处理功能已经在运行,就不执行它。在函数开始运行之前,我会检查名为image\u import\u running的数据库条目,看看它是否设置为false。如果是,则函数将运行。函数所做的第一件事就是将image\u import\u running设置为true。然后,当它全部完成后,我将其设置为false

从理论上讲,效果很好。我可以告诉你,从那以后,这个网站就再也没有崩溃过。但它有两个主要问题:

  • 如果用户在加载页面时关闭页面,则脚本永远不会完成图像处理,因此也不会将运行的image\u import\u设置回false。在手动设置为false之前,模板将不会再次处理图像

  • 如果脚本在处理图像时超时——如果队列中有许多图像,这是一个很大的可能性——您的问题本质上与第一个问题相同:脚本永远不会达到将image\u import\u running设置回false的程度

  • 为了处理第一个问题(我意识到的两个问题中的第一个),我在脚本中添加了
    ignore\u user\u abort(true)
    。它起作用了吗?我不知道,因为2号仍然是个问题。这就是我被难住的地方

    如果我可以询问服务器脚本是否正在运行,我可以这样做:

    if($import_running && $script_not_running) {
        $import_running = false;
    }
    
    但是如何设置
    $script\u不运行
    变量?我不知道

    我已将整个故事与您分享,以防您有其他出色的解决方案。

    尝试使用
    ignore\u user\u abort(真)即使用户离开并关闭浏览器,它也将继续运行


    您可能还希望在db记录中输入一个数字而不是true false,并设置可以一起运行的最大进程数

    正如其他人所建议的,最好将图像处理从请求本身移出

    作为临时“修复”,当处理作业开始时(例如,
    image\u import\u start
    ),在运行的
    image\u import\u旁边存储一个时间戳。这是一个非常粗糙的机制,但是如果您知道作业在超时之前可以运行的最长时间,那么脚本可以检查这段时间是否已过


    e、 例如,如果
    image\u import\u running
    仍然为真,但自
    image\u import\u开始以来,当前时间超过10分钟
    ,请运行处理。

    对于我来说,我仅将此简单想法用于文本文档。例如run.txt文件
    在顶部脚本中使用:

    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
    }
    
    并将其添加到脚本文件的末尾

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

    如果run word存在于
    run.txt
    中,它将不会运行

    运行cron肯定是更好的解决方案。将url存储在表中是一个好主意

    为了回答最初的问题,您可以使用exec运行ps auxwww命令(检查此页面:),并将函数移动到单独的php文件中

    exec("ps auxwww|grep myfunction.php|grep -v grep", $output);
    

    设置一个具有终止时间的瞬态,以限制操作,怎么样

    if(!get_transient( 'import_running' )) {
      set_transient( 'import_running', true, 30 ); // set a 30 second transient on the import.
      run_the_import_function();
    }
    

    我宁愿将作业存储到标记为挂起的数据库中,并设置一个cron作业来执行一次处理一个作业。

    只需在脚本顶部添加以下内容

    <?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 - $fileName\n";
            exit;   
        }
    
        // Your php script code.
    ?>
    
    
    
    不要在页面视图中执行此操作。提前做,或者使用cron作业。修复疾病-而不是像其他人建议的那样,最好将图像处理从请求本身移出。作为临时“修复”,当处理作业开始时(例如,
    image\u import\u start
    ),在运行的
    image\u import\u旁边存储一个时间戳。这是一个非常粗糙的机制,但是如果您知道作业在超时之前可以运行的最长时间,脚本可以检查该时间段是否已过(例如,如果
    image\u import\u running
    仍然为true,但自
    image\u import\u开始以来,当前时间超过10分钟,则无论如何都要运行处理).这里要澄清的是,问题是我有一个cron作业正在运行,它导入了大量的帖子,其中许多帖子都有相关的图片。图像是巨大的。我们只会使用很小比例的帖子,但是判断我们是否需要一个帖子的唯一方法(不会大大增加编辑的工作量)是如果用户试图查看它。这就是为什么我要导入第一页视图上的图像。所有这些都给了我一个想法。我不需要在用户查看页面时处理图像,而是可以将图像URL添加到一个数组中(以及它们关联的帖子)。然后,我可以偶尔运行一个cron作业,在清除数组之前导入并处理数组中的任何内容。嘿,这主意不错——谢谢你的灵感!这是一个好主意,但这取决于Web服务器使用的CGI接口。许多实现都有一个“硬超时”,不能用
    ignore\u user\u abort(true)
    覆盖;超时时间过后,进程将被强制终止。任何提及
    myfunction.php
    的进程都将使其跳闸。例如:
    vim myfunction.php
    php/a/total/different/myfunction.php
    。这包含竞争条件。两个进程都可以同时检查
    run.txt
    的内容,都可以看到它是空的,都可以写入它。如果程序死掉,它不会删除
    run.txt
    的内容,也不会运行任何程序。