大家好,我正在跟进我的问题Acquire_lock() not working. Bot still sending requests quickly. PHP + AJAX,我无法得到答案。
我简化了所有内容并拥有三个文件
所有在同一目录中,两个php文件的内容都是相同的:
<?php
$x = fopen("/var/www/abc.txt", "w");
if (flock($x, LOCK_EX|LOCK_NB)) {
print "No problems, I got the lock, now I'm going to sit on it.";
while (true)
sleep(5);
} else {
print "Didn't quite get the lock. Quitting now. Good night.";
}
fclose($x);
?>
然而,当我加载其中任何一个时,我得到第二条打印消息:“没有完全锁定。现在退出。晚安。”。
任何人都有任何想法,无论是对于这个问题,还是前者对于发生了什么?字面意思是我的智慧结束了。
一如既往地感谢你。
答案 0 :(得分:0)
如果您希望php脚本不退出,那么您需要阻止锁定。
flock文档说您可以通过指定第三个参数来完成。同时删除 LOCK_NB 可能有所帮助。
<?php
$x = fopen("/var/www/abc.txt", "w");
if (flock($x, LOCK_EX, 1)) {
print "No problems, I got the lock, now I'm going to sit on it.";
// wait for 5 seconds
sleep(5);
// Release the lock now so that next script is executed
flock($x , LOCK_UN);
} else {
print "Didn't quite get the lock. Quitting now. Good night.";
}
fclose($x);
?>
答案 1 :(得分:0)
以下是您脚本中发生的事情:
1)你的代码进入了一个无限循环while(true)
,并且它最终永远不会到达fclose()语句。
2)我在我的本地服务器上测试了两个文件:File1.php保持循环,而第二个file2.php给文件锁定消息立即(这意味着第一个文件正确锁定)。我之后尝试刷新这两个文件,但他们都没有通过锁定测试。
如果您使用的是PHP&gt; 5.3.2然后你必须手动解锁文件:
文件资源句柄关闭时的自动解锁是 除去。现在解锁总是必须手动完成。 Source
如果您使用的是旧版本的PHP,那么脚本将在脚本执行完毕后解锁文件,因为您将进入无限循环,脚本永远不会完成,因此文件永远不会被解锁。 / p>
此外,即使您停止在浏览器窗口中运行脚本,与该脚本相关的进程php-cgi.exe仍然在运行,必须从任务管理器手动终止(我自己验证了)
解决方案:
1) 要解决此问题并使脚本等待锁定,您需要首先确保脚本通过删除无限循环实际上正常停止:
这是一个将文件锁定30秒(删除循环)的脚本:
<?php
$x = fopen("/var/www/abc.txt", "w");
if (flock($x, LOCK_EX|LOCK_NB)) {
print "No problems, I got the lock, now I'm going to sit on it.";
sleep(30);
fclose($x); // it is good practice to always close even your PHP <5.3.2
}
else {
print "Didn't quite get the lock. Quitting now. Good night.";
}
?>
2)如果你在linux机器上,你可以使用LOCK_NB标志来确定文件是否被锁定。 LOCK_NB的用法应该是这样的:
while ( ! flock($f, LOCK_NB) )
{
sleep(1);
}
这将强制脚本每秒检查一次锁定并等待另一个脚本完成。
3)在完成后使用flock($fp, LOCK_UN)
显式删除锁而不是fclose();
总之,这就是您的代码的样子:
<?php
$x = fopen("/var/www/abc.txt", "w");
while(!flock($x,LOCK_NB)
sleep(1);
if (flock($x, LOCK_EX,true)) {
print "No problems, I got the lock, now I'm going to sit on it.";
sleep(30);
fflush($fp); // flush output before releasing the lock
flock($fp, LOCK_UN); // release the lock
} else {
print "Didn't quite get the lock. Quitting now. Good night.";
}
fclose($x);
?>