超时 PHP 中的函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10587323/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Timeout a function in PHP
提问by Mo3z
Is there a way to timeout a function? I have 10 minutes to perform a job. The job includes a for loop, here is an example:
有没有办法让函数超时?我有 10 分钟的时间来完成一项工作。该作业包括一个 for 循环,这是一个示例:
<?php
foreach($arr as $key => $value){
some_function($key, $value); //This function does SSH and SFTP stuff
}
?>
$arr has 15 elements and some_function() sometimes may take more than 1 minutes. In fact once it got hanged for 5 minutes.
$arr 有 15 个元素, some_function() 有时可能需要 1 分钟以上。事实上,一旦它被绞死了 5 分钟。
Is there a way I can timeout the function call and move on with next element in $arr?
有没有办法让函数调用超时并继续处理 $arr 中的下一个元素?
Thank you!!
谢谢!!
采纳答案by Mike B
It depends on your implementation. 99% of the functions in PHP are blocking. Meaning processing will not continue until the current function has completed. However, if the function contains a loop you can add in your own code to interrupt the loop after a certain condition has been met.
这取决于您的实施。PHP 中 99% 的函数都是阻塞的。意思是在当前功能完成之前不会继续处理。但是,如果函数包含循环,您可以添加自己的代码以在满足特定条件后中断循环。
Something like this:
像这样的东西:
foreach ($array as $value) {
perform_task($value);
}
function perform_task($value) {
$start_time = time();
while(true) {
if ((time() - $start_time) > 300) {
return false; // timeout, function took longer than 300 seconds
}
// Other processing
}
}
Another example where interrupting the processing IS NOT possible:
另一个不可能中断处理的示例:
foreach ($array as $value) {
perform_task($value);
}
function perform_task($value) {
// preg_replace is a blocking function
// There's no way to break out of it after a certain amount of time.
return preg_replace('/pattern/', 'replace', $value);
}
回答by Ray
PHP is single threaded... you have to use your OS's ability to fork another process.
PHP 是单线程的……您必须使用操作系统的能力来分叉另一个进程。
The only way I know how to do this is with the exec command to fork off another full process. Put the stuff you want timed in a separate script, call exec on the script, then immediately sleep for 10 min. If at 10 min the process is still running kill it. (you should have it's PID by making the command run the new php code in the background, getting it via command line and returning it from the exec command).
我知道如何做到这一点的唯一方法是使用 exec 命令来分叉另一个完整进程。把你想要计时的东西放在一个单独的脚本中,在脚本上调用 exec,然后立即休眠 10 分钟。如果在 10 分钟时进程仍在运行,则将其杀死。(您应该通过使命令在后台运行新的 php 代码,通过命令行获取它并从 exec 命令返回它来获得它的 PID)。
回答by Jacques
What you want is to use the pcntl_alarm function, which will trigger a SIGALRM signal on timeout.
您想要的是使用 pcntl_alarm 函数,该函数将在超时时触发 SIGALRM 信号。
For example:
例如:
// 10 minutes
pcntl_alarm( 600 );
pcntl_signal(SIGALRM, function() { print( "Timed-out!\n" ); exit( 0 ); });
Please see here the PHP manual for more on this: http://php.net/manual/en/function.pcntl-alarm.php
请在此处查看 PHP 手册以了解更多信息:http: //php.net/manual/en/function.pcntl-alarm.php
回答by aurora
You could try implementing this using 'curl'. Curl is -- from PHP -- mostly used to do HTTP/FTP stuff, but it supports many more protocols, including ssh/sftp. I've never done something ssh/sftp related using curl, so i can not give any additional advice, but you should be able to find additional information here on stackoverflow or somewhere else.
您可以尝试使用“curl”来实现这一点。Curl —— 来自 PHP —— 主要用于处理 HTTP/FTP 的东西,但它支持更多的协议,包括 ssh/sftp。我从来没有使用 curl 做过与 ssh/sftp 相关的事情,所以我不能提供任何额外的建议,但你应该能够在 stackoverflow 或其他地方找到更多信息。
There is an option "CURLOPT_TIMEOUT" you could use to configure the timeout for your request (there's also an option "CURLOPT_CONNECTTIMEOUT"). You can even specify the timeouts in millisecond resolution (CURLOPT_TIMEOUT_MS / CURLOPT_CONNECTTIMEOUT_MS).
您可以使用一个选项“CURLOPT_TIMEOUT”来配置请求的超时时间(还有一个选项“CURLOPT_CONNECTTIMEOUT”)。您甚至可以以毫秒为单位指定超时 (CURLOPT_TIMEOUT_MS / CURLOPT_CONNECTTIMEOUT_MS)。
Anyway: for a cronjob i would recommend to use an additional "lock-file" your script writes when it's started and removes, when it's finished running. You can check for this lock-file within your script so if cron triggers your script beforethe last run finished, you can just exit your script without any further doing. That ensures, that your script will not be executed multiple times in parallel.
无论如何:对于cronjob,我建议使用额外的“锁定文件”,您的脚本在启动时写入并在完成运行时删除。您可以在脚本中检查此锁定文件,因此如果 cron在上次运行完成之前触发了您的脚本,您可以直接退出脚本而无需进一步执行。这可确保您的脚本不会并行执行多次。
You can find more on the CURL options and CURL itself in the PHP documentation, too:
您也可以在 PHP 文档中找到有关 CURL 选项和 CURL 本身的更多信息:
You have to make sure, that your installed libcurl and/or curl for php supports SSH/SFTP, though:
不过,您必须确保已安装的 libcurl 和/或 curl for php 支持 SSH/SFTP:
etc.
等等。
Hope that helps ...
希望有帮助...
回答by D. Strout
Before starting into the loop, set a variable that remembers the time(). At the end of each iteration, check if the current time()is more than 60 seconds greater. If so, break. For instance:
在开始进入循环之前,设置一个记住time(). 在每次迭代结束时,检查电流time()是否大于 60 秒。如果是这样,break. 例如:
<?php
$startTime=time();
foreach($arr as $key => $value){
some_function($key, $value); //This function does SSH and SFTP stuff
if (time()-$startTime>60) break; //change 60 to the max time, in seconds.
}
?>
回答by Recognizer
Take a look at set_time_limit. Now the function itself isn't really want you want as it only takes into consideration execution time, meaning 5 seconds in real life might still be only 0.2 seconds execution. But the reason for looking at the link is for the comments. There's a couple solutions that users have posted.
看看set_time_limit。现在函数本身并不是你想要的,因为它只考虑了执行时间,这意味着现实生活中的 5 秒可能仍然只有 0.2 秒的执行时间。但是查看链接的原因是为了评论。用户发布了几个解决方案。
回答by user1418446
For those of you who are in command line, see how sleep is interrupted:
对于那些在命令行中的人,看看睡眠是如何被中断的:
echo date("H:i:s\n");
pcntl_signal(SIGALRM ,function($signal){
echo "arghhh! i got interrupted \n";
},true);
pcntl_alarm(3);
sleep(20);
pcntl_signal_dispatch();
echo date("H:i:s\n");
pcntl_alarm(3);
sleep(20);
echo date("H:i:s\n");
pcntl_signal_dispatch();
echo "end\n";

