2010-08-02 48 views
1

我有幾個由cron調用的php腳本。 cron作業每20分鐘運行一次。有時腳本會在幾分鐘內完成工作,有時需要超過20分鐘。網頁的單個實例

我想在這裏防止競爭條件。我想到的一種方式是在頁面運行時使用數據庫設置標誌,並在作業完成時刪除標誌。但我真的不想使用數據庫。

有沒有其他解決方案?

+2

每30分鐘運行一次cron作業? ;-) – Scharron 2010-08-02 12:44:55

+0

謝謝你的建議。它必須每20分鐘運行;) – Maximus 2010-08-02 12:50:21

回答

2

最好的方法(我用過)涉及將進程ID保存在「鎖定文件」中。

function getLock() { 
    //First, check to see if the script is already running 
    $data = @file_get_contents('path/to/process.pid'); 
    if ($data && posix_kill($data, 0)) { 
     throw new RuntimeException(
      'Unable To Attain Lock, Another Process Is Still Running' 
     ); 
    } 
    file_put_contents('path/to/process.pid', posix_getpid()); 
} 

基本上,它讀取文件,然後試圖posix_kill裏面包含的pid。請注意,當您使用0posix_kill的信號時,它只會告訴您呼叫是否成功(意味着該過程正在運行)。

這樣做有一個好處,即如果進程在沒有清理鎖定文件的情況下死掉,它會被檢測到並重新運行。

+0

所以,當工作完成後,我需要只是取消鏈接PID文件?如果我殺了PHP進程會發生什麼? – Maximus 2010-08-02 15:49:35

+1

您可以取消鏈接。這種方法的美妙之處在於你不必這樣做。所有文件都存儲'pid'。所以,即使你不解除鏈接,它仍然可以正常工作(只要另一個進程不是在同一個'pid'上啓動的,這不太可能)...如果該文件仍然存在,它會檢查看看存儲'pid'的進程是否仍在運行。如果不是(因爲它死了,你殺了它,或者它完成了),它會得到鎖並繼續執行...... – ircmaxell 2010-08-02 15:55:47

+0

完美工作! – Maximus 2010-08-02 17:41:49

1

您可以使用flock()鎖定預定義的「標誌」文件,並在啓動腳本之前檢查該文件是否仍然鎖定。

+1

我不會推薦這個,如果腳本死了怎麼辦? – thecodeassassin 2010-08-02 12:47:01

+0

是的,因爲這個原因,我沒有使用文件鎖定 – Maximus 2010-08-02 13:11:39

+0

正確 - 你可以使用某種超時,但它可能無法在這個頻繁的任務中工作。 – 2010-08-02 13:15:04

2

你可以使用一個標記文件或共享內存區,或任何的進程間通信的其他正常形式。鍍金解決方案將實施一個小批量排隊過程。

+0

你可以提供一個例子嗎? – Maximus 2010-08-02 12:50:39

+0

作業正在運行時創建文件,並在作業完成後將其刪除。如果作業再次運行,而另一個作業正在運行,則在開始之前檢查此文件。 – jigfox 2010-08-02 12:54:01

+0

批處理隊列處理?對不起,我不能。我真的是VMS男人,VMS包括批處理。你想要的是一個小程序,它讀取一個包含作業列表的文件,當它找到一個文件時,執行它,然後從文件中刪除它。這涉及到一些進程同步。克倫職位不會執行這項工作;他們會向文件附加一個請求。有人必須這樣做,也許網絡的一點拖網可能會出現一些東西。 – 2010-08-02 12:54:54

1

如果您創建一個pid文件來指示進程正在運行,請確保檢查文件的創建時間,並且已經設置了一個閾值,以確定過長的時間。這樣,如果你的工作在它有機會刪除它的pid文件之前就消失了,你的工作就不會停下來。