2012-04-01 72 views
0

Perl腳本需要接收ajax請求,向瀏覽器發回「成功」消息,然後「產生」一個進程在後臺運行。 (這個產生的過程可能需要10分鐘才能運行,所以我不希望瀏覽器等待 - 或發生apache超時)Perl發送ajax響應,然後exec()

我的印象是Perl exec()函數會這樣做。比使用fork()或system()更好,因爲它們應該等待響應。

但是,腳本似乎在等待exec()程序完成,然後將成功消息發送到瀏覽器。這裏是我的Perl腳本的末尾:

print "Content-type: text/html\n\n"; 
print "success"; # this gets returned via ajax 

exec $script_filename, $var1, $var2, $var3; 

一切正常,但直到$ SCRIPT_FILENAME結束運行瀏覽器未收到「成功」的消息。

我想要做的似乎與this previous post類似,但是那裏沒有足夠的細節。

任何想法?謝謝。

+0

fork()不會「等待響應」。 – pilcrow 2012-04-02 04:12:28

回答

0

我找到了另一個似乎解決我的問題的StackOverflow問題的答案 - 請參閱Paul Tomblin's response here

看來,如果Perl腳本執行exec(),然後Apache等待。但是,如果perl腳本首先執行fork,然後fork執行exec(),那麼一切都按預期工作。

這裏是它看起來像在我的代碼,替換什麼在我原來的職位:

use POSIX 'setsid'; 

$SIG{CHLD} = 'IGNORE'; 

# This should flush stdout. 
my $ofh = select(STDOUT);$| = 1;select $ofh; 

my $kpid = fork; 
if ($kpid) 
{ 
    # Parent process 
    print "Content-type: text/html\n\n"; 
    print "success"; # this gets returned via ajax 
} 
else 
{ 
    close STDIN; 
    close STDOUT; 
    close STDERR; 
    setsid(); 
    my $gpid = fork; 
    if (!$gpid) 
    { 
     open(STDIN, "</dev/null") ; 
     open(STDOUT, ">/dev/null") ; 
     open(STDERR, ">/dev/null") ; 
     # Child process 
     exec($script_filename, $var1, $var2, $var3) ; 
    } 
    exit 0; 
} 

感謝亞當確認立刻意識到什麼,我本來試圖做的是有缺陷的。

感謝喬納森爲我指出了正確的方向。

+0

恭喜修復!如果可以,請確保將您的答案標記爲「已接受」,以便其他人可以從您的成功中學習。乾杯〜 – 2012-04-02 14:58:32

+0

我會的。這讓我等了8個小時。 – egret 2012-04-02 18:55:41

2

Apache會在完成對瀏覽器的響應之前等待腳本完成。您應該安排一項作業在後臺運行,然後讓腳本終止。

爲了安排後臺作業,您可以將後臺任務處理器實現爲一個守護進程,它在執行它們之前通過IPC(例如通過UNIX域套接字)從您的perl腳本接受任務。或者,您可以使用現有的UNIX工具進行後臺作業調度,如atbatch。詳情請參閱this manpage

如果您需要非常高的可靠性,您可能還需要在向客戶端確認任務已安排之前,將任務保留到外部存儲器。

+0

+1'Apache將會等待'(但我不太確定其餘的)。使用'fork()'並讓子進程運行後臺進程和父進程(所以Apache停止等待)將解決問題。您不必使用複雜的調度('批處理'或'at'); 'fork()'已經足夠了。它可能會有好處;分叉的孩子具有可以簡化後臺處理的設置的上下文。 – 2012-04-01 19:57:14

+0

你是否在暗示這樣的事情:$ SIG {CHLD} ='IGNORE'; defined(my $ kid = fork)或死「不能fork:$!\ n「; 如果($小子){ 打印 」父已完成\ n「; } 其他{ #做一些耗時 } – egret 2012-04-01 19:59:38

+0

@JonathanLeffler從OP的代碼,似乎意圖是運行一個外部的命令/腳本,這很容易用at/batch完成,並且確保了更好的隔離(思考信號,進程組,文件描述符等)當需要父腳本的上下文時,fork() – 2012-04-01 20:27:39