有没有办法使函数超时?我有 10 分钟的时间来完成一项工作。该作业包括一个 for 循环,下面是一个示例:
<?php
foreach($arr as $key => $value){
some_function($key, $value); //This function does SSH and SFTP stuff
}
?>
$arr有 15 个元素,some_function(( 有时可能需要 1 分钟以上。事实上,一旦它被挂起了 5 分钟。
有没有办法让我的函数调用超时并继续处理$arr中的下一个元素?
谢谢!!
这取决于您的实现。 PHP 中 99% 的函数都是阻塞的。这意味着在当前函数完成之前,处理不会继续。但是,如果函数包含循环,则可以添加自己的代码,以便在满足特定条件后中断循环。
像这样:
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
}
}
另一个无法中断处理的示例:
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);
}
使用pcntl_alarm函数,它将在超时时触发SIGALRM信号。
例如:
// 10 minutes
pcntl_alarm( 600 );
pcntl_signal(SIGALRM, function() { print( "Timed-out!n" ); exit( 0 ); });
请参阅此处的PHP手册以获取更多信息:http://php.net/manual/en/function.pcntl-alarm.php
PHP 是单线程的...你必须使用操作系统的能力来分叉另一个进程。
我知道该怎么做的唯一方法是使用 exec 命令分叉另一个完整进程。 将您想要计时的内容放在单独的脚本中,在脚本上致电 exec,然后立即睡眠 10 分钟。 如果在 10 分钟后进程仍在运行,请将其杀死。(你应该通过让命令在后台运行新的 PHP 代码,通过命令行获取它并从 exec 命令返回它来拥有它的 PID(。
您可以尝试使用"curl"来实现这一点。Curl来自PHP - 主要用于做HTTP/FTP的东西,但它支持更多的协议,包括ssh/sftp。我从来没有使用 curl 做过与 ssh/sftp 相关的事情,所以我不能给出任何额外的建议,但你应该能够在这里找到关于 stackoverflow 或其他地方的其他信息。
有一个选项"CURLOPT_TIMEOUT"可用于配置请求的超时(还有一个选项"CURLOPT_CONNECTTIMEOUT"(。您甚至可以以毫秒分辨率 (CURLOPT_TIMEOUT_MS/CURLOPT_CONNECTTIMEOUT_MS( 指定超时。
无论如何:对于 cronjob,我建议使用脚本在启动时写入的额外"锁定文件",并在完成运行时删除。您可以在脚本中检查此锁定文件,因此如果 cron 在最后一次运行完成之前触发了脚本,您可以退出脚本而无需执行任何进一步操作。这样可以确保您的脚本不会并行执行多次。
您也可以在 PHP 文档中找到有关 CURL 选项和 CURL 本身的更多信息:
- http://www.php.net/manual/en/function.curl-setopt.php
- http://www.php.net/manual/en/book.curl.php
不过,您必须确保已安装的 libcurl 和/或 curl for php 支持 SSH/SFTP:
- 来自 PHP 的 SFTP - 未定义的常量CURLOPT_PROTOCOLS和CURLPROTO_SFTP?
- SFTP 从 PHP 内部
等。
希望有帮助...
在开始循环之前,设置一个记住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.
}
?>
看看set_time_limit。现在函数本身并不是你想要的,因为它只考虑执行时间,这意味着现实生活中的 5 秒可能仍然只有 0.2 秒的执行。但是查看链接的原因是为了评论。用户发布了几个解决方案。
对于那些使用命令行的人,请参阅睡眠是如何中断的:
echo date("H:i:sn");
pcntl_signal(SIGALRM ,function($signal){
echo "arghhh! i got interrupted n";
},true);
pcntl_alarm(3);
sleep(20);
pcntl_signal_dispatch();
echo date("H:i:sn");
pcntl_alarm(3);
sleep(20);
echo date("H:i:sn");
pcntl_signal_dispatch();
echo "endn";