PHP锁定不起作用。无法弄清楚为什么

时间:2015-04-18 03:43:09

标签: php mysql ajax locking bots

大家好,我正在跟进我的问题Acquire_lock() not working. Bot still sending requests quickly. PHP + AJAX,我无法得到答案。

我简化了所有内容并拥有三个文件

  • 的abc.txt
  • file1.php
  • file2.php

所有在同一目录中,两个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); 
?>

然而,当我加载其中任何一个时,我得到第二条打印消息:“没有完全锁定。现在退出。晚安。”。

任何人都有任何想法,无论是对于这个问题,还是前者对于发生了什么?字面意思是我的智慧结束了。

一如既往地感谢你。

2 个答案:

答案 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); 
?>