2012-10-17 3 views
0

symfony 1.4에서 프로세스를 여러 번 실행하지 못하게하는 방법이 필요합니다.symfony 1.4의 프로세스 잠금

다음과 같이 사용자가이 프로세스를 실행하면이 프로세스를 실행하려고하는 다른 사용자에게 프로세스가 실행 중임을 알리는 경고 메시지가 표시됩니다.

데이터베이스를 사용하지 않고 구현할 수 있습니까? 처음에

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 기능, register_shutdown_function()exitHandler 기능을 설정 :

+2

당신은 예를 들어'.lock' 파일을 작성하고 확인할 수 있습니다 사용하는 방법

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'; } } 
. 현재 사용자가 프로세스를 멈추었을 때'.lock' 파일을 지우는 것을 잊지 마십시오. – j0k

+0

나는 그 해결책을 고려했다. 그러나 사용자가 연결을 끊었거나 서버에 문제가 발생하면 파일은 삭제되지 않습니다. –

+0

하지만 데이터베이스를 사용하지 않으면 어려울 것입니다. 예를 들어, 사용자가 유휴 상태인지 (예를 들어 sfPdoSessionStorage를 사용하여) 너무 오랜 시간이 지난 후 '.lock' 파일을 재설정 할 수 있습니다. – j0k

답변

3

kirugan의 방법은 대부분의 경우에 잘 작동하지만 충돌 상황에 쉽게 영향을받을 수 있으며 충돌이 발생해도 멈출 수 있습니다.

다음은 더 강력한 해결책입니다. 그것은 PHP의 파일 잠금을 사용하므로 을 알고 있습니다. 나중에 잠금을 해제하는 것을 잊어 버리거나 프로세스가 충돌하면 자동으로 해제됩니다. 기본적으로 잠금을 얻는 것은 비 차단입니다 (즉, 잠금이 다른 프로세스에 의해 이미 보유 된 경우 getLock()은 즉시 FALSE를 반환합니다). 그러나 원하는 경우 통화 차단 (예 : 잠금을 사용할 수있을 때까지 대기)을 사용할 수 있습니다. 마지막으로 코드의 다른 부분에 대해 서로 다른 잠금을 설정할 수 있습니다. 자물쇠에 다른 이름을 사용하십시오.

유일한 요구 사항은 getLockDir()이 반환하는 디렉토리가 서버 쓰기 가능이어야한다는 것입니다. Lock Dir의 위치를 ​​자유롭게 변경하십시오.

참고 : flock()은 Windows에서 다르게 작동 할 수 있으므로 (Linux를 사용함), 문제가있는 경우 다시 확인하십시오.

myLock.class.php 프로세스를 실행할 때이 파일이 존재하는 경우

$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 
} 
+0

코드가 기적처럼 작동합니다. –

+0

'터치'로 경쟁 조건을 만들 수있는 예를 들어 주시겠습니까? – kirugan

+0

이것을 상상해보십시오 : 두 개의 요청이 동시에 들어오고 둘 다 lock()을 호출합니다. 요청 A는 if 문을 실행합니다. $ file은 존재하지 않으므로 죽지 않습니다.그러나 아직 '터치'라인을 실행하지 않았다. 이제 요청 B는 if 문을 실행합니다. $ file은 아직 존재하지 않으므로 죽지 않습니다. 이제 두 요청 모두 그들이 자물쇠를 가지고 있다고 생각합니다. 내 코드에서 flock()은 원자 단위로 보장되며 (한꺼번에 발생하고 OS에 의해 중단 될 수 없음) 두 프로세스가 다른 행을 차례대로 실행하더라도 하나만 잠금을 얻고 다른 하나는 잠금을 얻습니다. FALSE가 표시됩니다. –

1

여기이 내 기능입니다. 이 스 니펫을 같은 방법으로 클래스로 저장하거나 도우미 파일처럼 저장할 수 있습니다.

관련 문제