0

我需要一种方法来防止在 symfony 1.4 上的进程多次运行。

比如:当一个用户正在运行这个进程时,另一个试图运行这个进程的用户会收到一条警告消息,通知该进程正在运行。

有没有办法在不使用数据库的情况下实现它?

4

2 回答 2

3

kirugan 的方法可能在大多数情况下都有效,但它容易受到竞争条件的影响,并且在发生崩溃时可能会卡住。

这是一个更强大的解决方案。它使用 PHP 的文件锁定,因此您知道锁是原子的,如果您稍后忘记释放锁或您的进程崩溃,它会自动释放。默认情况下,获取锁是非阻塞的(即如果锁已经被另一个进程持有,getLock()将立即返回 FALSE)。但是,如果您愿意,您可以设置调用块(即等到锁可用)。最后,您可以为代码的不同部分设置不同的锁。只需为锁使用不同的名称。

唯一的要求是返回的目录getLockDir()必须是服务器可写的。随意更改锁定目录的位置。

注意:我认为flock () 在Windows 上的行为可能不同(我使用linux),所以请仔细检查它是否对您有问题。

myLock.class.php

class myLock
{
  /**
   * Creates a lockfile and acquires an exclusive lock on it.
   *
   * @param string $filename The name of the lockfile.
   * @param boolean $blocking Block until lock becomes available (default: don't block, just fail)
   * @return mixed Returns the lockfile, or FALSE if a lock could not be acquired.
   */
  public static function getLock($name, $blocking = false)
  {
    $filename = static::getLockDir() . '/' . $name;
    if (!preg_match('/\.lo?ck$/', $filename))
    {
      $filename .= '.lck';
    }
    if (!file_exists($filename))
    {
      file_put_contents($filename, '');
      chmod($filename, 0777); // if the file cant be opened for writing later, getting the lock will fail
    }
    $lockFile = fopen($filename, 'w+');
    if (!flock($lockFile, $blocking ? LOCK_EX : LOCK_EX|LOCK_NB))
    {
      fclose($lockFile);
      return false;
    }
    return $lockFile;
  }

  /**
   * Free a lock.
   *
   * @param resource $lockFile
   */
  public static function freeLock($lockFile)
  {
    if ($lockFile)
    {
      flock($lockFile, LOCK_UN);
      fclose($lockFile);
    }
  }

  public static function getLockDir()
  {
    return sfConfig::get('sf_root_dir') . '/data/lock';
  }
}

如何使用

$lockFile = myLock::getLock('lock-name');
if ($lockFile) {

  // you have a lock here, do whatever you want

  myLock::freeLock($lockFile);
}
else {
  // you could not get the lock. show a message or throw an exception or whatever
}
于 2013-03-14T14:18:28.513 回答
1

这是我的功能:

function lock(){
   $file = __DIR__ . '/file.lock';
   if(file_exists($file)){
        /* exit or whatever you want */
        die('ALREADY LOCKED');
   }
   touch($file);
}
function unlock(){
    $file = __DIR__ . '/parser.lock';
    if(file_exists($file)){
        unlink($file);
    }else{
        echoln("unlock function: LOCK FILE NOT FOUND");
    }
}

function exitHandler(){
     echoln('exitHandler function: called');    
         unlock();
}

开头使用lock函数,设置exitHandler函数在register_shutdown_function(). 您可以使用相同的方法将此片段保存为类或将其保存为帮助文件

于 2013-03-12T21:53:44.033 回答