2012-10-16 45 views
2

我有一個簡單的perl腳本,調用一個shell腳本,當從瀏覽器調用時總是「掛起」。我想在20秒後強制延長時間。當我在命令行中運行它時,沒有問題。但是,當我從瀏覽器中執行該腳本時,該腳本將執行但從未完成加載。所以我沒有得到頁面上的輸出。如果我殺死了命令行中的進程,瀏覽器就完成加載,並且內容顯示在瀏覽器中。perl警報不按預期工作

我做了大量的研究,似乎web服務器正在等待shell腳本完成,因爲shell腳本仍然有一個打開的標準輸出文件句柄。

這是我的代碼。

#!/usr/bin/perl 

use strict; 
use warnings; 

use CGI; 

my $q = new CGI; 

print $q->header; 

my $timeout = 10; 
my $pid = fork; 

if (defined $pid) { 
    if ($pid) { 

     # this is the parent process 
     local $SIG{ALRM} = sub { die "TIMEOUT" }; 

     alarm 10; 

     # wait until child returns or timeout occurs  
     eval { 
      waitpid($pid, 0); 
     }; 

     alarm 0; 

     if ([email protected] && [email protected] =~ m/TIMEOUT/) { 
      # timeout, kill the child process 
      kill 9, $pid; 
     } 
    } 
    else { 
     # this is the child process 
     # this call will never return. Note the use of exec instead of system 
     exec "/opt/bea/domains/fsa/scripts/start.sh"; 
    } 
} 
else { 
    die "Could not fork."; 
} 

如何強制頁面完成加載,無論shell腳本在一段時間後的狀態如何。

+1

你真的不問一個問題在這裏... – Ralgha

+0

好吧,我問在最後的問題:) – user1750930

+0

是假設腳本輸出任何東西到瀏覽器? – ikegami

回答

0

問題是腳本完成後,web服務器仍在等待所有創建的子進程(甚至由您創建)完成。最好的方法是使用setsid創建單獨的進程組。或者你甚至可以嘗試「double fork trick」,在那裏你從小孩那裏分叉,然後再從小孩那裏分叉。之後,第一個孩子將退出,第二個孩子成爲孩子,如果init。此外,確保(在兩種情況下)的孩子,你做的事:

close STDIN; 
close STDOUT; 
close STDERR;