2

ブラウザから呼び出されると常に「ハング」するシェルスクリプトを呼び出す単純なperlスクリプトがあります。20秒後に強制的にタイムアウトさせたいだけです。コマンドラインで実行しても問題はありません。しかし、ブラウザから実行すると、スクリプトは実行されますが、ロードが完了しません。そのため、ページに出力が表示されません。コマンドラインでプロセスを強制終了すると、ブラウザの読み込みが終了し、コンテンツがブラウザに表示されます。

私は多くの調査を行いましたが、シェルスクリプトにはまだ標準出力へのオープンファイルハンドルがあるため、Webサーバーはシェルスクリプトが終了するのを待っているようです。

これが私のコードです。

#!/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 ( $@ && $@ =~ 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.";
}

一定時間後にシェルスクリプトのステータスに関係なく、ページの読み込みを強制的に終了するにはどうすればよいですか。

4

1 に答える 1

0

問題は、スクリプトが終了した後も、Webサーバーは、作成されたすべての子(自分で作成したものも含む)が終了するのを待機していることです。それを処理する最良の方法は、で個別のプロセスグループを作成することですsetsidまたは、「ダブルフォークトリック」を試すこともできます。このトリックでは、子供からフォークしてから、もう一度フォークします。その後、最初の子が終了し、次の場合は2番目の子が子になりinitます。また、(どちらの場合も)子供に次のことを確認してください。

close STDIN;
close STDOUT;
close STDERR;
于 2012-10-23T09:23:53.853 に答える