2008-11-05 136 views
41

我試圖做一個PHP腳本,我已經完成腳本,但它需要10分鐘才能完成它旨在執行的過程。這不是一個問題,但我認爲我必須保持頁面加載所有這是令人討厭的。我是否可以擁有它,以便我開始此過程,然後在10分鐘後回來並查看它生成的日誌文件?PHP後臺進程

回答

50

那麼,你可以使用「ignore_user_abort(真)」

因此腳本將繼續工作(保持對腳本持續的眼睛,也許加上「set_time_limit(0)」)

但警告在這裏:你將無法停止腳本這兩條線:

ignore_user_abort(true); 
set_time_limit(0); 

除了可以直接訪問服務器,並有殺死進程! (去過那裏,做一個死循環,在自稱一遍又一遍,取得了服務器來嘎然停止,在得到了喊...)

+0

這是輝煌的。這也適用於WordPress的Ajax調用'wp_ajax_nopriv_your_trigger'。在你的鉤子中使用上面的兩個方法,並調用(可能使用調度器)http://yourdomain.com/wp-admin/admin-ajax.php?action=your_trigger – 2010-12-17 00:49:16

+0

工作就像一個魅力!我正在將文件上傳到我的服務器,然後使用此方法的腳本將其上傳到S3,以便我可以輕鬆地向用戶顯示上傳進度。我很爽快,其他請求和什麼不在我的網站。你看,這個文件在S3中,我的日誌顯示了進程。 :D – 2013-03-03 03:03:37

+0

@azure_ardee WordPress已經有了一個模擬cron系統來處理這樣的事情。請參閱http://codex.wordpress.org/Function_Reference/wp_cron – 2013-11-11 20:50:21

3

你可以使用ignore_user_abort() - 這樣的腳本將繼續,即使你關閉你的瀏覽器中運行或轉到其他頁面。

8

我在windows下這種過程有很多問題;我的情況有點不同,我不關心「腳本」的反應 - 我希望腳本啓動並允許其他頁面請求在忙於工作時通過。

出於某種原因;我遇到了問題,要麼掛起其他請求,要麼在約60秒後超時(在約20分鐘後,apache和php都設置爲超時);它也證明,無論如何5分鐘後(默認情況下)firefox超時,所以在那之後你不知道通過瀏覽器發生了什麼,而不改變Firefox的設置。

我結束了在使用過程中打開和處理close方法在命令行模式下打開了一個PHP像這樣:

pclose(popen("start php myscript.php", "r"));

這(使用開始)打開PHP程序,然後殺死開始進程離開PHP運行,無論它需要多長時間 - 再次,你需要殺死進程手動關閉它。它不需要你設置任何超時,你可以讓當前頁面調用它並繼續輸出更多的細節。

唯一的問題是,如果你需要發送腳本的任何數據,你要麼通過另一個來源或通過「命令行」作爲參數傳遞;這並不安全。

很好地爲我們所需要的工作,並確保腳本始終啓動,並允許運行沒有任何中斷。

26

聽起來像你應該有一個隊列和一個外部腳本來處理隊列。

例如,您的PHP腳本應該在數據庫表中放入一個條目並立即返回。然後,每分鐘運行一個cron檢查隊列併爲每個作業分配一個進程。

這裏的優點是你不會鎖定一個Apache線程10分鐘。

4

還有另一種選擇,你可以使用,運行腳本CLI ...它會在後臺運行,你甚至可以運行它作爲cronjob如果你想。

e.g

> #!/usr/bin/php -q 

<?php 

//process logs 

?> 

這可以設置爲一個cronjob並且將沒有時間限制執行....這樣的例子是用於基於Unix的操作系統雖然。

FYI 我有一個php腳本運行一個無限循環,它執行一些處理,並且已經運行了過去3個月不停。

2

想想Gearman

Gearman的是工作外包出去,以 多臺機器或流程的通用應用程序框架。它允許應用程序並行完成 任務,負載平衡處理以及在語言之間調用功能 。該框架可用於從高可用性網站到傳輸數據庫複製事件的各種 應用程序。

此擴展提供了用於編寫Gearman客戶端和 工人的類。 - 源PHP手冊

Gearman

1

ZUK的官方網站。

我敢肯定,這將工作:

<?php 

pclose(popen('php /path/to/file/server.php &')); 
echo "Server started. [OK]"; 

?> 

的 '&' 是很重要的。它告訴shell不要等待進程退出。

,你也可以在你的服務器停止命令在你的PHP使用此代碼(如 「bastiandoeen」 之稱)

ignore_user_abort(true); 
set_time_limit(0); 

​​
2

除了bastiandoeen的回答,您可以結合ignore_user_abort(true);cUrl請求

假的請求流產連接後設置一個較低的CURLOPT_TIMEOUT_MS並保持加工關閉:

function async_curl($background_process=''){ 

    //-------------get curl contents---------------- 

    $ch = curl_init($background_process); 
    curl_setopt_array($ch, array(
     CURLOPT_HEADER => 0, 
     CURLOPT_RETURNTRANSFER =>true, 
     CURLOPT_NOSIGNAL => 1, //to timeout immediately if the value is < 1000 ms 
     CURLOPT_TIMEOUT_MS => 50, //The maximum number of mseconds to allow cURL functions to execute 
     CURLOPT_VERBOSE => 1, 
     CURLOPT_HEADER => 1 
    )); 
    $out = curl_exec($ch); 

    //-------------parse curl contents---------------- 

    //$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); 
    //$header = substr($out, 0, $header_size); 
    //$body = substr($out, $header_size); 

    curl_close($ch); 

    return true; 
} 

async_curl('http://example.com/background_process_1.php'); 

NB

如果你想捲曲在不到一秒鐘的超時時間,你可以使用 CURLOPT_TIMEOUT_MS,雖然「Unix-like 系統」中存在bug /「功能」,導致libcurl立即超時,如果該值爲< 1000 ms,出現錯誤「cURL Error(28):Timeout reached reached」。該 解釋這種行爲是:

[...]

的解決方案是使用CURLOPT_NOSIGNAL

利弊

  • 無需切換輸入法禁用信號(兼容窗口& linux)
  • 無需設置NT連接通過頁眉和緩衝(獨立於瀏覽器和PHP版本)

利弊處理

  • 需要curl擴展

資源