如何解决不影响PHP-CLI的set_time_limit?
#!/usr/bin/php -q
<?php
set_time_limit(2);
sleep(5); // actually, exec() call that takes > 2 seconds
echo "it didn't work again";
Run Code Online (Sandbox Code Playgroud)
Pas*_*TIN 18
的max_execution_time限制,这是什么 set_time_limit规定,计数(至少在Linux上)是由PHP的过程中度过,而工作的时间.
引用手册的页面set_time_limit():
注:该
set_time_limit()功能和配置指令max_execution_time只影响脚本本身的执行时间.在确定脚本运行的最长时间时,不包括在
执行脚本之外发生的任何活动,例如系统调用system(),流操作,数据库查询等.
在测量时间真实的Windows上,情况并非如此.
当您正在使用时sleep(),您的PHP脚本无法正常工作:它只是在等待......所以您等待的5秒不会被max_execution_time限制考虑在内.
mje*_*jec 10
这里的解决方案是使用pcntl_fork().我担心它只是POSIX.PHP需要编译,--enable-pcntl而不是--disable-posix.您的代码应如下所示:
<?php
function done($signo)
{
// You can do any on-success clean-up here.
die('Success!');
}
$pid = pcntl_fork();
if (-1 == $pid) {
die('Failed! Unable to fork.');
} elseif ($pid > 0) {
pcntl_signal(SIGALRM, 'done');
sleep($timeout);
posix_kill($pid, SIGKILL);
// You can do any on-failure clean-up here.
die('Failed! Process timed out and was killed.');
} else {
// You can perform whatever time-limited operation you want here.
exec($cmd);
posix_kill(posix_getppid(), SIGALRM);
}
?>
Run Code Online (Sandbox Code Playgroud)
基本上它的作用是fork一个运行else { ... }块的新进程.在(成功)结束时,我们将警报发送回正在运行elseif ($pid > 0) { ... }块的父进程.该块具有用于警报信号(done()回调)的注册信号处理程序,该信号处理程序成功终止.在收到之前,父进程会休眠.超时sleep()完成后,它会向SIGKILL(可能是挂起的)子进程发送一个.
非常 hackish,但由于我经常使用 cli 脚本,所以我羞愧地承认过去曾进行过类似的 hack。需要 2 个脚本。
您的第一个 cron 脚本(挂起的脚本)将其启动时间和 processid 记录在一个平面文件中 -> 函数 getmypid 将成为您的朋友。每 (x) 分钟从 cron 运行的第二个脚本会检查平面文件,杀死所有已超过指定执行时间的文件,清除平面文件,甚至根据需要登录另一个文件。
祝你好运 ;)
更新:
想起了这个问题,又回来发帖了。在翻阅 Sebastian Bergmann 的 github 帐户时,我偶然发现了php-invoker。用作者的话来说:
用于调用具有超时功能的 PHP 可调用对象的实用程序类。
虽然当前的答案对于基于 Linux 的非便携式使用非常好,但如果需要跨平台解决方案,则对于那些在 windows 上运行的可怜的灵魂来说,该解决方案应该与 Windows 兼容。Bergmann 先生作为 PHP 大神,我完全保证脚本的质量。
你能尝试通过exec运行你的php并使用"超时"命令吗?(http://packages.ubuntu.com/lucid/timeout)
用法:超时[-signal] time命令.