2011-04-25 102 views
1

我有一個網頁向cgi腳本發送請求,該腳本基本上必須tar和壓縮可能超過50G的巨大目錄。我在我的cgi腳本中派生了一個進程,用於執行tarling任務,同時向父母腳本中的網頁發送響應消息。但是,父腳本(即使沒有waitpid($ pid,0))等待焦油過程結束,然後將味精發送到網頁,然後通過警告框打印。有沒有一種方法可以立即發送msg,以便用戶知道tarling過程已經啓動,並且該進程可以在後臺進行。我不想執行exec(),因爲我需要在創建此tar時捕獲任何錯誤球。如何同時運行子進程和父進程

另外,會不會有任何記憶的問題,而我試圖焦油這麼大的目錄?

$SIG{CHLD} = 'IGNORE'; 
$|++; 
$pid = fork(); 
if($pid){ sendResponse($data); exit; } 
elsif($pid == 0) 
{ 
    setsid(); 
    $gpid = fork(); 
    if(! $gpid) 
    { 
     qx(tar up big directories over 50G...); 
    } 
} 

回答

2

您最初的「身份」響應客戶端可能正在某個地方緩衝。如果CGI執行是正確設計,無緩衝輸出流或者請求刷新一個流應該導致所有的數據包被髮送到客戶端(它們可能被接收到的任何內容緩衝,但這是你無法控制的)。

請參閱Perl FAQ How do I flush/unbuffer an output filehandle? Why must I do this?瞭解如何不緩衝您的初始響應。

請注意,CGI環境也可能調用waitpid()或類似的方法,這就是爲什麼直到子進程存在之後才能看到結果的原因。如果您希望子進程在請求或客戶端消失後繼續存在,則需要將子進程與父進程關聯。請參閱perlipc中的Complete Dissociation of Child from Parent

由於您將要處理的數據量非常大(50G),這需要相當長的時間。很可能客戶端或服務器在等待tar結束時可能會遇到某種超時。爲了避免這種情況,您可以確保客戶端和服務器都瘋狂地長時間超時,或者在兩者之間定期發送數據以保持連接/請求處於活動狀態。您可能需要考慮讓tar進程解除關聯並讓客戶端週期性地向服務器查詢結果。最後,假設tar不寫入內存緩衝區,它應該是相對高效的內存(假設現代硬件)。但是,它可能會消耗大量的CPU和I/O。我肯定會對服務的安全性和潛在的(無意的)拒絕服務保持謹慎。

+0

謝謝!所以,如果我取消緩衝文件句柄($ |),我應該能夠立即發送響應。客戶端和服務器之間沒有數據交換,除了這個msg。爲了避免在客戶端打印'超時'消息,分離孩子是否明智? – Wilderness 2011-04-25 23:19:59

+0

如果父母和孩子之間沒有數據交換,也沒有父母徘徊的理由,那麼分離就有意義。 此外,在父母關閉時(假設孩子被分離),任何輸出都應發送給客戶。所以,如果解除關聯孩子,你不需要緩存標準輸出。 – IndyGreg 2011-04-26 00:48:59

+0

完美!萬分感謝 !將嘗試一下。 – Wilderness 2011-04-26 01:41:18