如果脚本已经在运行,不要运行它

时间:2021-02-07 16:25:35

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.

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

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.

我的解决方案是,如果它已经在运行,就不执行图像处理功能。在函数开始运行之前,我将检查名为image_import_running的数据库条目,看看它是否被设置为false。如果是,函数就会运行。函数做的第一件事就是将image_import_running设置为true。然后,一切结束后,我把它设为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.

    如果用户在加载页面时关闭了页面,则脚本永远不会完成对图像的处理,因此不会将image_import_running返回为false。模板将永远不会再处理图像,直到它被手动设置为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.

    如果脚本在处理图像时超时——如果队列中有许多图像,这是一种很有可能的情况——那么本质上,您将遇到与第1号相同的问题:脚本永远不会到达将image_import_running回为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.

为了处理第1个问题(我意识到的两个问题中的第一个),我在脚本中添加了ignore_user_abort(true)。它工作了吗?我不知道,因为2号还是个问题。这就是我难住了。

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.

但是如何设置$script_not_running变量呢?难倒我了。

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

我跟你分享了整个故事以防你有更好的解决办法。

7 个解决方案

#1


1  

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

试着用ignore_user_abort(真正的);即使用户离开并关闭浏览器,它仍将继续运行。

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

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

#2


1  

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.

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

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.

例如,如果image_import_running仍然为真,但是当前时间比image_import_started之后的10分钟还要长,那么无论如何都要运行处理。

#3


1  

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


1  

I would rather store the job into database flagging it pending and set a cron job to execute the processing one job at a time.

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

#5


0  

For Me i use just this simple idea with a text document. for example run.txt file
in the top script use :

对我来说,我只是在文本文档中使用了这个简单的想法。例如跑步。顶部脚本中的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
}

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

这将通过检查runt检查脚本是否已经工作。txt内容,如果运行中存在运行字。它不会运行

#6


0  

Running a cron would definitively be a better solution. Idea to store url in a table is a good one.

运行cron肯定是一个更好的解决方案。在表中存储url的想法很好。

To answer to the original question, you may run a ps auxwww command with exec (Check this page: How to get list of running php scripts using PHP exec()? ) and move your function in a separated php file.

要回答最初的问题,您可以使用exec运行ps auxwww命令(请查看此页面:如何使用php exec()获取运行php脚本的列表?)并将函数移动到一个分开的php文件中。

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

#7


-2  

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 - $fileName\n";
        exit;   
    }

    // Your php script code.
?>

#1


1  

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

试着用ignore_user_abort(真正的);即使用户离开并关闭浏览器,它仍将继续运行。

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

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

#2


1  

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.

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

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.

例如,如果image_import_running仍然为真,但是当前时间比image_import_started之后的10分钟还要长,那么无论如何都要运行处理。

#3


1  

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


1  

I would rather store the job into database flagging it pending and set a cron job to execute the processing one job at a time.

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

#5


0  

For Me i use just this simple idea with a text document. for example run.txt file
in the top script use :

对我来说,我只是在文本文档中使用了这个简单的想法。例如跑步。顶部脚本中的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
}

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

这将通过检查runt检查脚本是否已经工作。txt内容,如果运行中存在运行字。它不会运行

#6


0  

Running a cron would definitively be a better solution. Idea to store url in a table is a good one.

运行cron肯定是一个更好的解决方案。在表中存储url的想法很好。

To answer to the original question, you may run a ps auxwww command with exec (Check this page: How to get list of running php scripts using PHP exec()? ) and move your function in a separated php file.

要回答最初的问题,您可以使用exec运行ps auxwww命令(请查看此页面:如何使用php exec()获取运行php脚本的列表?)并将函数移动到一个分开的php文件中。

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

#7


-2  

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 - $fileName\n";
        exit;   
    }

    // Your php script code.
?>