在symfony 1.4中锁定进程

时间:2012-10-17 08:28:54

标签: php symfony1 symfony-1.4

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

类似于:当用户运行此进程时,尝试运行此进程的其他用户将收到一条警告消息,通知该进程正在运行。

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

2 个答案:

答案 0 :(得分: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
}

答案 1 :(得分: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()功能。您可以使用相同的方法将此片段保存为类,或者将其保存为辅助文件