有一个很好的技巧可以绕过时间限制,但如果做得不好,它可能会滞后于您的服务器。基于这个脚本,我编写了纯 PHP CRON 替代方案。
您所做的是,您使 HTTP 客户端断开连接,但您保持脚本运行。这是最重要的——然后,脚本可以调用自己而不会卡在 istelf 上。
为此,发送 http 标头 Content-Length 很重要。
<?php
ignore_user_abort (true); //Tells PHP to ignore connection state
ob_start();
echo "Loop started\n";
$size = ob_get_length();
header("Content-Length: $size"); //Send exact output size to make sure client disconnects
header("Connection: close"); //Tells client to disconnect
ob_end_flush();
ob_flush();
flush(); //Clean all buffers
if(session_id()!="")
session_write_close(); //Close the session so that the user can use other scripts on the site
/*Here, the script runs even if client is connected*/
?>
现在,有一个非常危险的递归部分。您应该创建一个文件,告诉脚本它已经在运行以避免多个线程。像这样:
if(file_exists("secure_key"))
exit;
else
file_put_contents("secure_key",time());
因为你说你正在同步一些数据,你可能需要一个文件(或 MySql 表)来存储有关同步过程的信息。这将可以通知用户请求进度,也许使用 AJAX,就像你想要的那样。这将使整个应用程序看起来非常专业 :)
你可能知道,但如果它是 FOR 或 WHILE 循环,在其中你正在同步,那么将开始时间保存在常量中也很棒,这样你就可以退出并毫无问题地保存:
define("STARTTIME",time()); //Right now
define("MAXTIME",ini_get('max_execution_time')); //Max execution time
define("SAFE_EXIT_TIME", 4); //4 seconds to save & quit
/*preparation*/
while(time()-(STARTTIME-SAFE_EXIT_TIME)<MAXTIME) {
/*Synchronize*/
}
unlink("secure_key"); //delete the antistuck file
get_headers(/*scriopt url*/); //call itself
exit; //quit