AIM /动机
我想写一个应该一直运行的服务。但是,当它已经运行时,不应该再次启动该服务。
使用案例
用户X打开页面myService.php并通过单击页面上的按钮启动服务。之后关闭浏览器。 一段时间后,另一个用户打开浏览器并尝试启动该服务。 但该服务应该只启动一次。
(SEMI)PSEUDO CODE
<?php
ignore_user_abort(TRUE);
set_time_limit(0);
$sleepTime = 60;
while(1){
if( serviceAlreadyStarted() ){
echo "Service has already been started.";
exit;
}
if( shouldServiceBeStopped() ){
echo "Service has been stopped.";
exit;
}
// DO SOMETHING
sleep($sleepTime);
}
?>
预期行为
在第二次再次启动服务时,用户会立即收到消息 。
实际行为
在第二个条件退出第一个调用shouldServiceBeStopped()
之前,脚本的第二次调用没有响应答案 0 :(得分:1)
tldr:不要让用户进入第二个循环,检查服务是否正在运行之前他们可以按一个按钮进入循环。
我会在数据库或JSON文件中存储一个值(ini文件也可以)。然后,当用户首次加载页面时,读取该值并查看它是否已经启动。然后,您可以直接向用户显示该进程已启动的消息,而不是让他们按下按钮启动它,然后向他们显示消息。它减少了一个步骤并使用户更容易,它还应解决第二个循环一直运行直到第一个循环停止的问题。
问题在于,如果您的脚本在运行时崩溃,则会将文件标记为打开。有两种方法可以解决这个问题。第一个是你的stopService
函数可以强制文件退出,并且在你的where循环中,如果它检测到这个值退出。这要求用户停止服务。第二种方式,也就是我推荐的方式,是记录服务的日期/时间戳,每次循环开始时都会更新文件中的日期/时间。然后在serviceAlreadyStarted()
函数中,您可以检查日期/时间是否在有效期内。如果不是您知道脚本崩溃并且可以向用户显示错误消息。
我注意到你已经添加了一条评论,你几乎已经这样做了,但文件仍保持打开状态。确保在读取/设置值后立即关闭文件。你的循环执行速度太快,以至于它打开和关闭文件的速度太快,第二个副本也无法访问它。如果是这种情况,我只允许循环每100个左右循环打开文件,这应该允许程序的其他实例访问该文件。
答案 1 :(得分:0)
@Styphon
我已经尝试了很多可能的方法但没有成功。请考虑以下代码。我将描述一些对我来说毫无意义的具体案例
案例1 文件serviceStarted.txt存在。没有正在通话的电话。我打电话给剧本并立即得到答案&#34;服务已经开始&#34;。没有延迟。
案例2 serviceStarted.txt不存在。我打电话给剧本。已创建第一个循环运行和文件。使用另一个选项卡或浏览器,我再次调用脚本。需要大约20秒,直到收到服务正在运行的消息。
案例3(最有趣的一个) 与情况#2类似,但我在20秒之前手动在/相关文件夹中创建/复制serviceShouldBeStopped.txt(仅在第一次调用后4秒)。这导致第一和第二循环同时停止。是不是有点奇怪?
// Very first check:
if (is_file("serviceStarted.txt")) {
echo "<br> Service has already been started.";
} else {
while (1) {
// This check is aquivalent to the shouldServiceBeStopped()
// I copy this txt manually to the folder in order to stopp the first call
if (is_file("serviceShouldStopped.txt")) {
echo "Service stopped.";
exit;
}
// The first call should create this file
if (!is_file("serviceStarted.txt"))
file_put_contents("serviceStarted.txt", "any content");
sleep(60);
}
}
<强>更新强>
// This if statement used in second call
if (isset($_GET['noloop'])) {
echo "loop should not be executed";
}
else {
while (1) {
// This check is aquivalent to the shouldServiceBeStopped()
// I copy this txt manually to the folder in order to stopp the first call
if (file_exists("serviceShouldStopped.txt")) {
echo "Service stopped at " . date("H:i:s");
exit;
}
sleep(60);
}
}
&#13;