flock php锁不成功是因为在isRunning()方法退出后,$file_lock没有继续使用导致的,其解决办法就是确保在整个PHP生命期内,文件句柄都不会被释放即可。
本文操作环境:windows7系统、PHP7.1版、DELL G3电脑
flock php 锁不成功怎么办?
php flock失效问题解决:
这两天给自己的业余项目写了一个方法,用来避免crontab调度的php脚本并发执行。
做法
一般通过使用文件锁flock方法,令相同的PHP脚本采用非阻塞锁同一个磁盘文件,如果文件被占用则会报错,从而可以脚本立即退出。
现象
但实践中发现,在controller文件中直接flock是可以实现的,当把flock的逻辑封装到其他文件的一个函数中后就失效了。
原因
调试了半天,突然想起来以前就遇到过这个神坑。。
错误代码如下:
class Crontab
{
public static function isRunning() {
global $argv;
$ident = [];
foreach ($argv as $idx => $value) {
$ident[] = $idx . '=' . urlencode($value);
}
$ident = md5(implode('&', $ident));
$lockDir = \Yii::getAlias('@app/runtime/crontab/');
@mkdir($lockDir, 0755, true);
$file_lock = fopen($lockDir . $ident, 'w+');
$wouldBlock = 0;
flock($file_lock, LOCK_EX | LOCK_NB, $wouldBlock);
return $wouldBlock;
}
}
class Crontab
{
public static function isRunning() {
global $argv;
$ident = [];
foreach ($argv as $idx => $value) {
$ident[] = $idx . '=' . urlencode($value);
}
$ident = md5(implode('&', $ident));
$lockDir = \Yii::getAlias('@app/runtime/crontab/');
@mkdir($lockDir, 0755, true);
$file_lock = fopen($lockDir . $ident, 'w+');
$wouldBlock = 0;
flock($file_lock, LOCK_EX | LOCK_NB, $wouldBlock);
return $wouldBlock;
}
}
根据命令行参数生成唯一hash值,代表该PHP任务。
创建锁文件,执行flock非阻塞锁,返回wouldBlock标识锁是否已被占用。
我在脚本入口调用了Crontab::isRunning()方法,发现并发启动脚本后,总是能获得锁。
错误原因是:isRunning()方法退出后,$file_lock没有继续使用,被PHP垃圾回收,$fp文件句柄关闭导致锁自动释放。
解决
class Crontab
{
static $file_lock = null;
public static function isRunning() {
global $argv;
$ident = [];
foreach ($argv as $idx => $value) {
$ident[] = $idx . '=' . urlencode($value);
}
$ident = md5(implode('&', $ident));
$lockDir = \Yii::getAlias('@app/runtime/crontab/');
@mkdir($lockDir, 0755, true);
self::$file_lock = fopen($lockDir . $ident, 'w+');
$wouldBlock = 0;
flock(self::$file_lock, LOCK_EX | LOCK_NB, $wouldBlock);
return $wouldBlock;
}
}
class Crontab
{
static $file_lock = null;
public static function isRunning() {
global $argv;
$ident = [];
foreach ($argv as $idx => $value) {
$ident[] = $idx . '=' . urlencode($value);
}
$ident = md5(implode('&', $ident));
$lockDir = \Yii::getAlias('@app/runtime/crontab/');
@mkdir($lockDir, 0755, true);
self::$file_lock = fopen($lockDir . $ident, 'w+');
$wouldBlock = 0;
flock(self::$file_lock, LOCK_EX | LOCK_NB, $wouldBlock);
return $wouldBlock;
}
}
确保在整个PHP生命期内,文件句柄都不会被释放即可,所以保存在类静态成员变量里。
--结束END--
本文标题: flock php 锁不成功怎么办?
本文链接: https://www.lsjlt.com/news/524.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2023-03-24
2023-03-22
2023-03-06
2023-03-06
2023-02-18
2023-02-16
2023-02-15
2023-02-09
2023-02-03
2023-01-13
回答
回答
回答
回答
回答
回答
回答
回答
回答
0