2012-05-08 19 views
1

我有一個PHP的cronjob系統。我有一個名爲cron.php的文件,並想檢查它是否沒有加載,請加載它。這個文件只運行一次對我來說非常重要,我需要如何定義它已經運行的方式。我不能使用任何系統功能,如exec,system,...你有任何解決方案嗎?如何確保一次PHP腳本加載

注意:我運行我的腳本通過CURL和include_one和require_once不適用於這種情況。

+2

您的意思是說,如果現有的程序已經在執行,您是否希望避免運行cron作業cron.php? (因爲這與目前得到的答案有很大的不同,所以你應該澄清一下..) – Ben

+0

先生看到我的答案,並讓我知道我是否落後於某處 –

+1

您將不得不將腳本的最後執行時間存儲在某處數據庫,文本文件)。然後檢查最後一次執行時間/日期(用戶ID等),只有在給定條件(超時)時才執行腳本。 – djot

回答

7

你可以使用flock()鎖定php文件本身,像這樣:

<?php 

class Lock{ 
    private $fp; 
    function __construct(){ 
     $this->fp=fopen(__FILE__,'r'); 
     if (!flock($this->fp,LOCK_EX|LOCK_NB)) { 
      die('already running !'.PHP_EOL); 
     }  
    } 
    function __destruct(){ 
     flock($this->fp,LOCK_UN); 
     fclose($this->fp); 
    } 
} 

$lock=new Lock(); 


// simulate some processing 
sleep(60); 


echo "END"; 
?> 
+0

如果Apache服務器重新啓動LOCK過期或不? – IVIR3zaM

+1

@ IVIR3zaM:如果腳本被殺死,鎖定也會到期。 (不知道如果apache殺死腳本,如果它重新啓動,但我會這樣認爲) – stewe

+1

對,忘了羊羣。有一些討論,在不同的服務器配置下,可靠的羣體有多可靠,但現在看起來相當可靠? - 我也認爲apache在正常啓動時會殺死運行腳本 – cypherabe

2

您可以只使用require_onceinclude_once

require_once將拋出一個PHP致命錯誤(將停止執行),如果該文件無法評估。 include_once會拋出PHP警告(執行可能會繼續)。

// Require tasks.php to run once 
require_once 'path/to/tasks.php'; 

// Attempt to run tasks.php and only once 
include_once 'path/to/tasks.php'; 
1

可以使用require_onceinclude_once

既包括和要求語句的一般語法如下:

include "file_to_load.php"; 
include_once "file_to_load.php"; 

當使用include_once/require_once報表,文件無法加載或執行多次。如果嘗試使用這兩種方法之一加載文件兩次,它將被忽略。因爲在腳本中多次定義相同的函數是不可接受的,所以這些函數允許開發人員根據需要包含腳本,而不必檢查它是否先前已加載過。

備註從外部文件返回值的功能僅限於include_once語句。 require_once聲明不能以這種方式使用。

+0

這是不正確的。我通過CURL運行我的腳本。 include_one是爲每個客戶端,我希望我的腳本運行一次爲所有客戶 – IVIR3zaM

1
include_once('class.php'); 

php.net指出

的include_once語句包括和腳本的執行過程中運行指定文件 。這是一種類似於 include語句的行爲,唯一的區別是如果文件中的代碼 已包含在內,則不會再包含它。顧名思義,它只會包含一次。

0

您可以使用require_once或include_once。

,如果你是混淆使用什麼那麼這兩者之間的區別是,

require_once將停止執行上面的代碼中,trwos致命的錯誤,如果上述文件未找到 所以如果你想前面的代碼繼續即使文件沒有找到,那就不要使用它。

其中include_once將繼續執行前面的代碼。

2

你的問題基本上等同於「檢查PHP腳本仍在運行」

請參閱本

Check if a php script is still running

+0

它是好的,但不能正常工作,在我的腳本許多作品執行,可能需要很長時間,從秒傳遞,在這種情況下,我的腳本認爲它沒有運行並再次運行 – IVIR3zaM

2

如果我理解正確的話,你要阻止cron.php腳本從第二次由cron開始,它不會從另一個PHP腳本調用? (在這種情況下,require_once將是正確的答案)

據我所知,你需要存儲一個標誌,指示你的腳本運行,並刪除該標記在腳本的結尾。

取決於你的環境,你既可以創建一個小文件,即.lock或在數據庫中存儲狀態=鎖定條目。

編輯:下面是一個使用文件的方法一個小的代碼示例:

<?php 
// cron.php 
$path = '/path/to/your/data/directory/'; 
if (file_exists($path . '.lock') { 
    die('cron.php is already running'); 
} 
// if script reaches this point, it is not locked -> create a lock 
file_put_contents($path . '.lock', 'lockfile created at ' . now()); 

//... your code.... 

//unlocking 
unlink($path . '.lock'); 
?> 
+0

是的,你瞭解它。它叫槽CURL。但你的想法有問題,也許Apache重新啓動,我的腳本沒有結束取消鏈接。鎖定文件,然後我的系統永遠關閉 – IVIR3zaM

+0

謝謝,我通過使用flock()解決它的朋友建議 – IVIR3zaM

0

您可以使用數據庫進行這種情況下,在數據庫中輸入頁面,在第二欄輸入數據,檢查是否加載(例如,'0'如果尚未加載,則加載'1')。加載頁面時,最初將該行的值保存爲'0',將該列更新爲'1'

2

如果使用捲曲那麼我相信你正在使用cURL來請求一個頁面,如http://domain.com/cron.php。通過cURL/wget/browser/etc請求腳本的機器無法知道腳本是否已經在服務器上執行。但是,你可以配置你cron.php腳本只運行一次:

<?php 
// attempt to obtain a lock 
$fp = fopen(basename(__FILE__) . ".lock", "w"); 
if (flock($fp, LOCK_EX | LOCK_NB) === false) { 
    echo basename(__FILE__) . ": already running\n"; 
    exit(-1); 
} 

// code goes here 
echo date("Y-m-d H:i:s") . ": cron job started\n"; 
sleep(30); 
echo date("Y-m-d H:i:s") . ": cron job ended\n"; 

// release the lock 
flock($fp, LOCK_UN); 
fclose($fp); 

的代碼示例使用PHP flock功能。 LOCK_EX標誌告訴PHP它需要獲得排他鎖;即不允許其他進程訪問該文件。 LOCK_NB告訴PHP它不應該阻塞(等待鎖被釋放)並立即返回false。兩個開關一起確保第二個進程在第一個進程鎖定時不能鎖定文件。

+0

謝謝,我只有一個問題。當Apache服務器重新啓動這個鎖被刪除或沒有? – IVIR3zaM

+0

我測試它並閱讀更多關於它,是的,當Apache重新啓動所有鎖定發佈。謝謝 – IVIR3zaM

+1

@ IVIR3zaM:我在窗戶上安裝了Apache;似乎等待PHP流程完成;但我不確定如果Apache(或PHP進程)被_killed_會發生什麼情況。我在PHP CLI上測試了腳本,當我殺死腳本或使用CTRL + C終止腳本時它正確釋放了鎖。 PHP文檔還指出,鎖定是_advisory,而不是mandatory_,這可能意味着鎖定機制是殺死安全的。 –