为什么我的php flock在运行两次命令时没有检测到现有锁?

为什么我的php flock在运行两次命令时没有检测到现有锁?,php,symfony,flock,splfileobject,Php,Symfony,Flock,Splfileobject,稍微解释一下,我有一个Symfony2设置。我正在使用一个扩展的抽象命令类。我希望这些批处理中的任何一个都只能运行一次。我的目标是创建一个锁文件,我打开并聚集它,以便在php脚本以任何可能的方式死掉时自动释放锁 为了实现这一点,我创建了一个名为Lock的类。这个类扩展了SplFileObject,基本上是一个在某处创建*.lock(通常是/var/lock/*)的包装器。现在我发现这个锁有问题。我确实有一个使用fopen和flock的设置。由于某种原因,它再也检测不到它了 我创建了一个OOP结构

稍微解释一下,我有一个Symfony2设置。我正在使用一个扩展的抽象命令类。我希望这些批处理中的任何一个都只能运行一次。我的目标是创建一个锁文件,我打开并聚集它,以便在php脚本以任何可能的方式死掉时自动释放锁

为了实现这一点,我创建了一个名为Lock的类。这个类扩展了SplFileObject,基本上是一个在某处创建*.lock(通常是/var/lock/*)的包装器。现在我发现这个锁有问题。我确实有一个使用fopen和flock的设置。由于某种原因,它再也检测不到它了

我创建了一个OOP结构,基本上实现了我想要的功能:

  • 确定锁定文件的名称(使用文件夹)
  • 创建一个锁对象
    • 如果目录和锁文件不存在,则创建它们
    • 调用SplFileObject::_构造()
  • 锁定文件
我既不能使用句柄也不能使用spl文件对象。如果我运行脚本,让它休眠15秒,然后在另一个控制台中运行相同的脚本,我将得到一个结果,脚本成功地锁定了文件,flock返回true。如果我在同一个脚本中的同一个锁文件上创建了两个锁对象,那么我在第一个锁上得到true,在第二个锁上得到false,这意味着第二次它无法获得锁。剧本似乎很管用

但是,当我在两个脚本中使用两个锁运行脚本2次时,我在两个脚本中都得到True和false。。。这意味着它似乎无法跨脚本正确锁定文件:/

有没有人能告诉我我做错了什么?我已经检查了文件名,并且在我运行脚本的两次中都是相同的。我尝试了多种权限,如77775733,但没有区别

我这样称呼它(只是课堂的一部分):

Lock.php
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;
  }
}
?>