0

symfony1.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 に答える