如何使用 Cron Job 让 PHP 脚本永久运行?

10
<?php
 while(true){
 //code goes here.....
 }
  ?>

我想制作一个PHP Web服务器,那么如何使用Curl让这个脚本永久运行?


1
你需要的是 while(true),没错它会一直运行直到发生某些事情(最好是由你指定的中断条件)。 - Adi
@AdnanShammout 它会在一段时间后自动终止。PHP内置了一个最大执行时间设置,除非您在代码中修改该设置。 - Dexter Huinda
@DexterHuinda,PHP执行限制仅适用于从Web浏览器运行时。当作为命令php server.php运行时,该限制不适用。为什么有人想要从Web浏览器永久运行服务器呢? - Adi
@AdnanShammout 一个嵌入式Java程序,小应用可以在浏览器内永久运行,并且您可以直接通过浏览器访问管理界面。大多数人无法负担托管在可以直接访问shell的服务器上,因此基于浏览器的实现是一个选择。 - Dexter Huinda
需要注意的是,这将消耗CPU资源,因为while(true)会让CPU不断执行指令,例如:永远执行cmp。如果没有真正的工作要做,请考虑在循环内部加入睡眠机制。 - Accountant م
4个回答

23

不要忘记将最大执行时间设置为无限制(0)。

如果您的意图是这样,最好确保您不要运行多个实例:

ignore_user_abort(true);//if caller closes the connection (if initiating with cURL from another PHP, this allows you to end the calling PHP script without ending this one)
set_time_limit(0);

$hLock=fopen(__FILE__.".lock", "w+");
if(!flock($hLock, LOCK_EX | LOCK_NB))
    die("Already running. Exiting...");

while(true)
{

    //avoid CPU exhaustion, adjust as necessary
    usleep(2000);//0.002 seconds
}

flock($hLock, LOCK_UN);
fclose($hLock);
unlink(__FILE__.".lock");

如果是在CLI模式下,只需运行该文件。

如果在Web服务器上的另一个PHP中,你可以像这样启动必须无限运行的PHP文件(而不是使用cURL,这样可以消除依赖):

$cx=stream_context_create(
    array(
        "http"=>array(
            "timeout" => 1, //at least PHP 5.2.1
            "ignore_errors" => true
        )
    )
);
@file_get_contents("http://localhost/infinite_loop.php", false, $cx);

或者您可以使用类似于以下方式的Linux Cron启动wget:

`* * * * * wget -O - http://localhost/infinite_loop.php`

您可以通过使用bitsadmin在Windows计划任务中运行一个包含以下内容的.bat文件来开始:

bitsadmin /create infiniteloop
bitsadmin /addfile infiniteloop http://localhost/infinite_loop.php
bitsadmin /resume infiniteloop

@Tiberiu-IonuțStan,那么当您需要终止请求时,您实际上如何终止请求呢? - Pacerier
@Tiberiu-IonuțStan,你是什么意思? - Pacerier
3
作为程序员,你会预见到根据某些条件或甚至外部标志需要自动终止的需求,并将其放在正在运行的代码(无限循环.php内)中。 - oxygen
1
@Tiberiu-IonuțStan,是的,但总会存在一些错误。您的意思是我们没有办法终止一段不良脚本吗? - Pacerier
@Parcerier,你的意思是你刚刚忽略了我给你的解决方案吗? - oxygen
显示剩余2条评论

3
要让 PHP 代码永远运行,需要以下步骤:
  • set_time_limit(0); // 这样 PHP 才不会像正常情况下终止,如果你将要处理的内容需要很长时间才能完成
  • 设置用于保持页面活动的处理程序 [通常是通过设置客户端脚本以在一定时间间隔内调用同一页] 参见 setInterval(), setTimeout()

编辑: 但是,如果您将设置一个 cron 作业,则可以避免使用客户端处理。

编辑: 我的建议是,除非您有一个告诉它在一段时间后退出循环的代码,否则不要使用无限循环。请记住,您将使用 cron 作业调用同一页,因此保持循环无限没有意义。[编辑] 否则,您将需要像 @Tiberiu-Ionuț Stan 建议的锁定系统,以便每次调用 cron 作业时只运行1个实例。


1

默认情况下,不行,因为PHP有执行时间限制。 请参见:http://www.php.net/manual/en/info.configuration.php#ini.max-execution-time

您可以通过设置值或在脚本中调用set_time_limit来使其永久运行(http://php.net/manual/en/function.set-time-limit.php)。

但我不建议这样做,因为PHP(由HTTP请求调用)不是设计为具有无限循环。如果可以的话,请改用本地脚本,或者按间隔请求页面以频繁执行任务。

如果您的网站经常被其他人浏览,您可以在每个页面上执行此操作。

(想象一下,如果有人多次请求脚本,您将有多个实例正在运行)


这仅适用于从Web浏览器运行时。 - Adi
请问您能否指导我完成推理过程?我不明白curl如何表明是从Web浏览器中运行的。 - Adi
@AdnanShammout,我的错,我应该定义HTTP请求而不是“Web浏览器”。 - Alvin Wong
2
我不明白为什么使用 curl 就意味着你是从 HTTP 请求中运行的!你确定你知道 curl 的工作原理吗?Curl 可以帮助你在脚本内部进行 HTTP 请求,它与你如何运行该脚本(HTTP 请求或命令行)无关。 - Adi
请查看我的答案,了解如何以不同的方式启动您的无限脚本。 - oxygen
显示剩余2条评论

0
只有在脚本中设置set_time_limit(0),否则它将在配置中设置的max_execution_time后停止执行,这样你就可以实现它。
而且你正在使用while(true)条件,这将使你的脚本一直运行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接