为什么我的php flock在运行两次命令时没有检测到现有锁?
稍微解释一下,我有一个Symfony2设置。我正在使用一个扩展的抽象命令类。我希望这些批处理中的任何一个都只能运行一次。我的目标是创建一个锁文件,我打开并聚集它,以便在php脚本以任何可能的方式死掉时自动释放锁 为了实现这一点,我创建了一个名为Lock的类。这个类扩展了SplFileObject,基本上是一个在某处创建*.lock(通常是/var/lock/*)的包装器。现在我发现这个锁有问题。我确实有一个使用fopen和flock的设置。由于某种原因,它再也检测不到它了 我创建了一个OOP结构,基本上实现了我想要的功能:为什么我的php flock在运行两次命令时没有检测到现有锁?,php,symfony,flock,splfileobject,Php,Symfony,Flock,Splfileobject,稍微解释一下,我有一个Symfony2设置。我正在使用一个扩展的抽象命令类。我希望这些批处理中的任何一个都只能运行一次。我的目标是创建一个锁文件,我打开并聚集它,以便在php脚本以任何可能的方式死掉时自动释放锁 为了实现这一点,我创建了一个名为Lock的类。这个类扩展了SplFileObject,基本上是一个在某处创建*.lock(通常是/var/lock/*)的包装器。现在我发现这个锁有问题。我确实有一个使用fopen和flock的设置。由于某种原因,它再也检测不到它了 我创建了一个OOP结构
- 确定锁定文件的名称(使用文件夹)
- 创建一个锁对象
- 如果目录和锁文件不存在,则创建它们
- 调用SplFileObject::_构造()
- 锁定文件
namespace Something\Component\File;
use Symfony\Component\Filesystem\Filesystem;
/**
* Creates a new SplFileObject with access to lock and release locks
* Upon creation it will create the lock file if not exists
*
* The lock works by keeping a stream open to the lock file instead
* of creating/deleting the lock file. This way the lock is always
* released when the script ends or crashes.
*
* create a file named /var/lock/something/something.lock
* <example>
* $lock = new Lock('something');
* $lock->lock();
* $lock->release();
* </example>
*
* create a file named /var/lock/something/my-lock-file.lock
* <example>
* $lock = new Lock('something/my-lock-file');
* $lock->lock();
* </example>
*
* NOTE: locks that are not released are released
* automatically when the php script ends
*
* @author Iltar van der Berg <ivanderberg@something.nl>
*/
class Lock extends \SplFileObject implements Lockable
{
/**
* @param string $file_name
* @param string $open_mode
* @param Filesystem $filesystem
* @param string $lock_directory
*/
public function __construct($file_name, $open_mode = 'r+', Filesystem $filesystem = null, $lock_directory = '/var/lock')
{
$filesystem = $filesystem ?: new Filesystem();
$file = self::touchLockFile($file_name, $lock_directory, $filesystem);
parent::__construct($file, $open_mode);
}
/**
* Returns true if the lock is placed, false if unable to
*
* @return boolean
*/
public function lock()
{
return $this->flock(LOCK_EX | LOCK_NB);
}
/**
* Returns true if the lock is released
*
* @return bool
*/
public function release()
{
return $this->flock(LOCK_UN);
}
/**
* Attempts to create a lock file for a given filename and directory
* it will return a string if the file is touched
*
* @param string $file_name
* @param string $lock_directory
* @param Filesystem $filesystem
* @return string
*/
private static function touchLockFile($file_name, $lock_directory, Filesystem $filesystem)
{
$lock_file_path = explode('/', $file_name);
$lock_file = array_pop($lock_file_path);
$path = "$lock_directory/" . (empty($lock_file_path)
? $lock_file
: implode('/', $lock_file_path));
$lock_file = "$path/$lock_file.lock";
if(!$filesystem->exists($path) || !is_dir($path)) {
$filesystem->mkdir($path);
}
return $lock_file;
}
}
?>
namespace Something\Component\File;
使用Symfony\Component\Filesystem\Filesystem;
/**
*创建具有锁定和释放锁定访问权限的新SplFileObject
*创建时,它将创建锁文件(如果不存在)
*
*锁的工作原理是保持流对锁文件打开
*创建/删除锁定文件的步骤。这样,锁就永远锁着了
*脚本结束或崩溃时释放。
*
*创建一个名为/var/lock/something/something.lock的文件
*
*$lock=新锁(“某物”);
*$lock->lock();
*$lock->release();
*
*
*创建一个名为/var/lock/something/my-lock-file.lock的文件
*
*$lock=新锁(“某物/我的锁文件”);
*$lock->lock();
*
*
*注意:未释放的锁将被释放
*当php脚本结束时自动执行
*
*@作者伊尔塔·范德伯格
*/
类锁定扩展\SplFileObject实现可锁定
{
/**
*@param string$文件名
*@param string$open_模式
*@param Filesystem$Filesystem
*@param string$lock_目录
*/
公共函数构造($file\u name,$open\u mode='r+',Filesystem$Filesystem=null,$lock\u directory='/var/lock')
{
$filesystem=$filesystem?:新文件系统();
$file=self::touchLockFile($file\u name,$lock\u directory,$filesystem);
父项::u构造($file,$open_模式);
}
/**
*如果已放置锁,则返回true;如果无法锁定,则返回false
*
*@返回布尔值
*/
公共函数锁()
{
返回$this->flock(LOCK_EX | LOCK_NB);
}
/**
*如果释放锁,则返回true
*
*@returnbool
*/
公共功能发布()
{
返回$this->flock(锁定);
}
/**
*尝试为给定文件名和目录创建锁定文件
*如果触摸文件,它将返回一个字符串
*
*@param string$文件名
*@param string$lock_目录
*@param Filesystem$Filesystem
*@返回字符串
*/
私有静态函数touchLockFile($file\u name、$lock\u directory、Filesystem$Filesystem)
{
$lock_file_path=explode(“/”,$file_name);
$lock\u file=array\u pop($lock\u file\u path);
$path=“$lock\u directory/”(空($lock\u file\u path)
?$lock_文件
:内爆(“/”,$lock_file_path));
$lock_file=“$path/$lock_file.lock”;
如果(!$filesystem->exists($path)| |!is_dir($path)){
$filesystem->mkdir($path);
}
返回$lock_文件;
}
}
?>
我敢打赌,锁或文件被销毁的时间比您想象的要早,因为拥有这些对象的函数返回,从而使这些对象符合垃圾收集的条件。您对问题的描述令人困惑。“两个脚本上的true和false”是什么意思?您使用的是什么操作系统?@David在第一个代码块的lockCommand()中检查我的注释。@Jay Ubuntu和CentOS(是的,我已经检查了/var/lock在我们的系统上是否兼容)。编辑:我的本地机器运行Ubuntu来澄清:)我打赌锁或文件被销毁的时间比你想象的要早,因为拥有这些对象的函数返回,从而使对象符合垃圾收集的条件。在这种情况下,我让lockCommand()返回我的锁对象,并将其存储在某个地方。因为当我的睡眠(15)超出范围时,对象被移除,我将不再拥有锁。我的解决方案是将其存储在Command类中,以便在我的命令退出之前它不会消失。
namespace Something\Component\File;
use Symfony\Component\Filesystem\Filesystem;
/**
* Creates a new SplFileObject with access to lock and release locks
* Upon creation it will create the lock file if not exists
*
* The lock works by keeping a stream open to the lock file instead
* of creating/deleting the lock file. This way the lock is always
* released when the script ends or crashes.
*
* create a file named /var/lock/something/something.lock
* <example>
* $lock = new Lock('something');
* $lock->lock();
* $lock->release();
* </example>
*
* create a file named /var/lock/something/my-lock-file.lock
* <example>
* $lock = new Lock('something/my-lock-file');
* $lock->lock();
* </example>
*
* NOTE: locks that are not released are released
* automatically when the php script ends
*
* @author Iltar van der Berg <ivanderberg@something.nl>
*/
class Lock extends \SplFileObject implements Lockable
{
/**
* @param string $file_name
* @param string $open_mode
* @param Filesystem $filesystem
* @param string $lock_directory
*/
public function __construct($file_name, $open_mode = 'r+', Filesystem $filesystem = null, $lock_directory = '/var/lock')
{
$filesystem = $filesystem ?: new Filesystem();
$file = self::touchLockFile($file_name, $lock_directory, $filesystem);
parent::__construct($file, $open_mode);
}
/**
* Returns true if the lock is placed, false if unable to
*
* @return boolean
*/
public function lock()
{
return $this->flock(LOCK_EX | LOCK_NB);
}
/**
* Returns true if the lock is released
*
* @return bool
*/
public function release()
{
return $this->flock(LOCK_UN);
}
/**
* Attempts to create a lock file for a given filename and directory
* it will return a string if the file is touched
*
* @param string $file_name
* @param string $lock_directory
* @param Filesystem $filesystem
* @return string
*/
private static function touchLockFile($file_name, $lock_directory, Filesystem $filesystem)
{
$lock_file_path = explode('/', $file_name);
$lock_file = array_pop($lock_file_path);
$path = "$lock_directory/" . (empty($lock_file_path)
? $lock_file
: implode('/', $lock_file_path));
$lock_file = "$path/$lock_file.lock";
if(!$filesystem->exists($path) || !is_dir($path)) {
$filesystem->mkdir($path);
}
return $lock_file;
}
}
?>