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:
从理论上讲,它非常有效。这个网站从那以后就没有崩溃过,我可以告诉你。但它有两个主要问题:
-
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。
-
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.
?>