我有一个perl CGI程序,它使用fork()
启动一个子进程。这个孩子做了一些长时间的(大约60秒)计算,并最终将结果保存到tmp文件中。父级应该将控件返回到浏览器,浏览器将显示进度消息,并定期检查子级是否已写入其tmp文件;文件出现后,将显示结果。代码如下:
# Get a unique name for this job
my $guid = Data::GUID->new;
my $id = $guid->as_hex;
# Do the fork
my $pid = fork;
if (!defined $pid) {
die "cannot fork: $!";
# Child does this
} elsif ($pid == 0) {
# Do some calculations
# Save results in a filename with $id
# Parent does this
} else {
# Return the location of the tmp files to the client
return "Content-Type: text/html\n\n", $id;
# Browser uses contents of $id to check for the result file
}
我最初是在RedHat Linux上设置的,它运行得很好。不过,现在我正试图将它移植到运行Ubuntu的服务器上,而父服务器似乎正在等待长时间运行的子服务器完成它的返回。我认为是这样,因为浏览器在计算期间挂起,从不显示进度页,计算完成后立即跳转到结果。
我怀疑这与fork仿真有关,但我不确定,我还没有找到解决办法。谢谢你的建议。
编辑:这段代码是子程序的一部分-我使用CGI::Application,所以调用代码只是“使用”这段代码。因此返回语句。不过,我怀疑这是问题的原因,因为自从从Red Hat(它工作的地方)移植到Linux(它不工作的地方)之后,我就没有接触过代码。
最佳答案
Randal Schwartz的Watching long processes through CGI提供了一个有用的例子。分叉很简单:
if ( my $pid = fork ) { # parent does
delete_all(); # clear parameters
param( 'session', $session );
print redirect( self_url() );
}
elsif ( defined $pid ) { # child does
close STDOUT; # so parent can go on
unless ( open F, "-|" ) {
open STDERR, ">&=1";
exec "/usr/sbin/traceroute", $host;
die "Cannot execute traceroute: $!";
}
本文的其余部分将解释如何帮助用户跟踪正在运行的作业。
关于linux - fork 并返回而无需等待perl中的 child ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47576643/