2011-08-25 43 views
3

我正在使用supervisor(http://supervisord.org/)來守護一個相當標準的PHP腳本。該腳本的結構是這樣的:如何檢測PHP CLI腳本處於掛起狀態

while (1) { 
// Do a SQL select 
// for any matching rows, do something 
// if I have been running for longer than 60 mins, exit 
} 

今天,這個腳本(它已經相當穩定一段時間了)掛起。它沒有崩潰(即發出SIGHUP或者SIGTERM信號),這會提醒supervisord重啓該過程。它在處理過程中沒有遇到任何錯誤,這些錯誤或者被腳本捕獲,或者至少引發了致命的錯誤並退出。而不是這些「可捕捉」的場景,它只是坐在那裏。我們確實有一個cron作業設置,每小時運行一次以通過supervisorctl鉤子重新啓動腳本,因爲似乎普遍認爲PHP腳本在內存方面存在漏洞,如果長時間運行,很可能會重新啓動。重啓後,腳本正常恢復運行。

我的問題:我如何檢測到這個腳本已經掛起?我甚至無法開始診斷或解決這個問題,爲什麼它掛起,如果我不知道該狀態的警報。我正在尋找這方面的軟件解決方案,或者我可以採用一些方法來自己編寫解決方案(無論是PHP,Python,Perl還是shell)。

該腳本使用PHP 5.2.6編寫,並在最新的RHEL 5服務器上運行。

請讓我知道,如果我可以分享任何額外的信息,如果它可以幫助一個更真棒的解決方案。

謝謝!

Shaheeb R.

回答

2

由於這是腳本掛起的情況,因此PHP可能不會處理任何可以檢測到此掛起的附加代碼。出於這個原因,我建議修改腳本以保存日誌。這將允許主腳本讓它外的任何東西知道它仍然在運行,並且有一些很好的更新,它還可以幫助查明事情發生錯誤的地方。

可以將日誌記錄寫入文件或數據庫,並且應至少包含腳本狀態的指示符,例如上次修改日期。如果這個腳本沒有持續運行,那麼還應該指出它正在運行或已經停止。在你給出的例子中,日誌寫入會在while循環內至少發生一次,可能更多。它需要花費時間/資源來打開指針或數據庫連接,所以我建議只記錄需要的內容。 (注意:如果使用文本文件的方法,該文件將需要在每次寫入後立即被關閉。)

例子:

while (1) { 
    log('Running SQL select'); 
    // Do a SQL select 
    log('Results retrieved'); 
    // for any matching rows, do something 
    // (check log) if I have been running for longer than 60 mins, exit 
} 

function log($msg) { 
    // Write timestamp, $msg to log 
} 

一個單獨的腳本將需要檢查的日誌和報告任何錯誤,如果它受到主要劇本懸念的影響,這可能會有問題,但我無法想到替代方案。

關於記憶,如果你還沒有使用mysql_free_result你應該試試看。

+0

mysql_free_result是defini非常有趣,以前沒有遇到過。關於您建議嘗試從外部腳本記錄和監視此日誌:這對我們可能是可行的。我們已經在腳本中執行應用程序日誌記錄,因此它將構成日誌觀察器來監視它。 –

+0

作爲日誌觀察者,我們取得了SEC(http://simple-evcorr.sourceforge.net/)的良好成功,我們可以使用此工具構建解決方案。我得說,我很希望有一個'現成的'解決方案! –

0

這很簡單!只需計算從循環開始到當前執行點的時間差。

$starttime = microtime(true); 
while (1) 
{ 
    //Do your stuff here 
    //More SQL, whatever you need 


    //Put this at the end of the loop 
    $curtime = microtime(true); 
    $timetaken = $curtime - $starttime; 
    if($timetaken > (60 * 60)) 
    { 
     break; 
    } 
} 

microtime(true)將返回秒自Unix紀元,所以如果我們減去我們從當前時間開始的時間,我們有時間採取/經過,並退出循環,如果一切都結束了60*60秒。

+0

唯一的問題,我在這裏看到如果在進行任何操作之前進程掛起...(即:代碼停止執行) – Jakub

+0

也是如此,正如我在第一篇文章中所描述的那樣,我們已經在計算時間來限制腳本的運行時間。 –

1

我的建議與@Shroder所描述的類似,但要稍微深入一點。每次運行時,你會創建一個日誌/數據庫記錄,那麼它將被加蓋時間戳+事務感知(你會更新在運行開始時的交易processing,然後做的時候,簽署了與completed的條目。

在側你會運行一個簡單的cron檢查,看看當前的時間比你觸發大(60分鐘,等)使用時間戳和交易狀態。在這一點上你扔警報等;

+0

我喜歡在日誌中包含事務狀態的想法。這個「最終交易」令牌可能是日誌觀察者可以追蹤的東西。也許在end-tx令牌之間設置一段時間間隔,如果超過該間隔,則強制重新啓動腳本。 –

+0

@Shaheeb Roshan,如果你喜歡答案,不要忘記把upvote或標記爲答案(綠色選中標記) – Jakub

相關問題