我有一个简单的perl脚本,它调用一个shell脚本,当从浏览器调用时它总是“挂起”。我只想在20秒后强制暂停一下。当我在命令行中运行它时没有问题。但是当我从浏览器执行此操作时,脚本将被执行,但永远不会完成加载。所以我没有得到页面上的输出。如果我在命令行中删除-9进程,浏览器将完成加载,内容将显示在浏览器中。
我做了很多研究,似乎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 ( $@ && $@ =~ 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脚本的状态如何,如何强制页面完成加载。
答案 0 :(得分:0)
问题是,在脚本完成后,webserver仍在等待创建的所有子项(甚至由您创建)完成。如何处理它的最佳方法是使用setsid
创建单独的流程组。或者你甚至可以尝试“double fork trick”,你在那里分叉,从孩子那里再来一次。之后,如果init
,第一个孩子将退出,第二个孩子将成为孩子。还要确保(在两种情况下)孩子都这样做:
close STDIN;
close STDOUT;
close STDERR;