According to the documentation:
max_execution_time only affect the execution time of the script itself.
Any time spent on activity that happens outside the execution of the script
such as system calls using system(), stream operations, database queries, etc.
is not included when determining the maximum time that the script has been running.
This is not true on Windows where the measured time is real.
测试证实了这一点:
不会超时
<?php
set_time_limit(5);
$sql = mysqli_connect('localhost','root','root','mysql');
$query = "SELECT SLEEP(10) FROM mysql.user;";
$sql->query($query) or die($query.'<br />'.$sql->error);
echo "You got the page";
会超时
<?php
set_time_limit(5);
while (true) {
// do nothing
}
echo "You got the page";
我们的问题是,我们真的希望PHP在给定的时间之后暂停,无论它在做什么(因为我们不知道如果我们知道我们在提供页面失败的情况下资源很忙可接受的时间,如10秒)。我们知道我们可以使用诸如MySQL wait_timeout之类的设置来进行SQL查询,但页面超时将取决于执行的查询数。
有些人试图提出workarounds,但似乎无法实施。
问:有没有一种简单的方法可以在Linux上获得真正的PHP max_execution_time
,还是我们可以更好地在其他地方超时,例如Apache
级别?
答案 0 :(得分:5)
这是一个非常棘手的建议,但如果您愿意修改并重新编译PHP,它肯定会做您想要的。
在功能Zend/zend_execute_API.c
处查看https://github.com/php/php-src/blob/master/Zend/zend_execute_API.c(文件为zend_set_timeout
)的PHP源代码。这是实现时间限制的功能。以下是它在不同平台上的工作原理:
在Windows上,创建一个新线程,在其上启动一个计时器,当它完成时,将名为timed_out
的全局变量设置为1,PHP执行核心为每个指令检查此变量,然后退出(非常简化)
在Cygwin上,使用itimer和ITIMER_REAL,它测量真实的时间,包括任何睡眠,等待等等,然后引发一个信号,它将中断任何处理和停止处理
在其他unix系统上,将itimer与ITIMER_PROF一起使用,ITIMER_PROF仅测量当前进程所花费的CPU时间(但在用户模式和内核模式下都是如此)。这意味着等待其他进程(如MySQL)不计入其中。
现在您要做的是将Linux上的itimer从ITIMER_PROF更改为ITIMER_REAL,当然您需要手动,重新编译,安装等。这两者之间的另一个区别是它们在使用时也会使用不同的信号计时器用完了。所以我的建议是改变ifdef:
# ifdef __CYGWIN__
到
# if 1
这样你就可以设置ITIMER_REAL和PHP等待SIGALRM的信号。
无论如何,这个想法都是未经测试的(我将它用于一些非常具体的系统,其中ITIMER_PROF被破坏,似乎工作),不受支持等。使用它需要您自担风险。它本身可以与PHP本身一起使用,但它可能会破坏其他模块,如果它们出于任何原因,使用SIGALRM信号或其他计时器,在Apache的PHP 和中。
答案 1 :(得分:1)
这是一个陈旧且回答的问题。但是为了帮助别人,我想指出request_terminate_timeout
php-fpm选项。如果你正在使用PHP-FPM,那很可能就是你需要的。
如果设置,此选项允许您告诉PHP-FPM在N秒后终止请求,无论PHP做什么。
有关详细信息,请参阅http://php.net/manual/en/install.fpm.configuration.php#request-terminate-timeout。
答案 2 :(得分:-2)
来自httpd.conf:
超时:接收和发送超时之前的秒数
超时300