2011-02-05 115 views
0

我想創建一個PHP文件,如果它已經在運行,它將不會運行。這裏是我正在使用的代碼:如何在PHP中鎖定文件?

<?php 

class Test { 
    private $tmpfile; 

    public function action_run() { 
     $this->die_if_running(); 
     $this->run(); 
    } 

    private function die_if_running() { 
     $this->tmpfile = @fopen('.refresher2.pid', "w"); 

     $locked = @flock($this->tmpfile, LOCK_EX|LOCK_NB); 
     if (! $locked) { 
      @fclose($this->tmpfile); 
      die("Running 2"); 
     } 
    } 

    private function run() { 
     echo "NOT RUNNNING"; 
     sleep(100); 
    } 
} 

$test = new Test(); 
$test->action_run(); 

問題是,當我從控制檯運行它,它的工程很好。但是當我嘗試從瀏覽器運行它時,許多實例可以同時運行。這是在Windows 7,XAMPP,PHP 5.3.2上。我想操作系統認爲它是相同的過程,因此功能下降。是否有跨平臺的方式來創建這種類型的PHP腳本?

+1

雞羣文檔稱LOCK_NB在Windows上不受支持。使用沉默運算符(@)是一個非常糟糕的主意,你實際上可能會抑制你得到的錯誤。 – Evert 2011-02-05 13:42:29

+0

@Evert,感謝您的建議,我複製了鎖定代碼,但沒有刪除@的,雖然沒有顯示任何錯誤 – Fluffy 2011-02-05 13:46:07

回答

0

沒有什麼可看的。你不能像這樣使用羊羣。

您可以使用system()啓動另一個爲您執行鎖定的(php)進程。但缺點:

  • 您需要進行進程間通信。想想如何告訴其他程序什麼時候釋放鎖等等。你可以使用stdin進行消息傳遞,並使用3個常量或其他東西。在這種情況下,它仍然相當簡單
  • 這對性能不利,因爲您不斷創建昂貴的流程。

另一種方法是啓動另一個運行的程序。你用一些IPC的方式連接到它(可能只是使用一個tcp通道,因爲它是跨平臺的),並允許這個程序管理文件訪問。這個程序也可能是一個無限循環的php腳本,但在Java或其他支持多線程的語言中進行編碼可能會更簡單。

另一種方法是利用現有的資源。爲鎖創建一個虛擬數據庫表,爲該文件創建一個條目,然後執行錶行鎖定。

另一種方法是不使用文件,而是使用數據庫。

0

前段時間我有類似的問題。 我需要一個計數器,返回的號碼是唯一的。 我使用了一個鎖定文件,只有當這個實例能夠創建鎖定文件時,才允許用當前編號讀取文件。

而不是計數,也許你可以允許腳本運行。 訣竅是讓嘗試幾次(如5)與之間的一個小的等待/睡眠。

function GetNextNumber() 
{ 
    $lockFile = "lockFile.txt"; 
    $lfh = @fopen($lockFile, "x"); 
    if (!$lfh) 
    { 
    $lockOkay = false; 
    $count = 0; 
    $countMax = 5; 

    // Try ones every second in 5 seconds 
    while (!$lockOkay & $count < $countMax) 
    { 
     $lfh = @fopen($lockFile, "x"); 
     if ($lfh) 
     { 
     $lockOkay = true; 
     } 
     else 
     { 
     $count++; 
     sleep(1); 
     } 
    } 
    } 

    if ($lfh) 
    { 
    $fh = fopen($myFile, 'r+') or die("Too many users. "); 
    flock($fh, LOCK_EX); 
    $O_nextNumber = fread($fh, 15); 
    $O_nextNumber = $O_nextNumber + 1; 
    rewind($fh); 
    fwrite($fh, $O_knr); 
    flock($fh, LOCK_UN); 
    fclose($fh); 

    unlink($lockFile); // Sletter lockfilen 
    } 

    return $O_nextNumber; 
}