如何完全在IIS下的Perl CGI中处理进程

时间:2011-04-04 14:46:55

标签: perl iis cgi background-process

感谢此处的一些其他精彩帖子(例如thisthat),我有几种可靠的方法来处理Perl脚本中的流程。

但是,在我的环境(Windows Server 2003上的IIS6)中,它似乎并不完全是背景。拿这个脚本:

use CGI::Pretty qw(:standard);
print header;
print start_html;
print "hi<br>";
system(1,qw(sleep 10));
print "bye";
print end_html;

睡眠过程运行时,浏览器将保持“连接”状态10秒钟。 “hi”和“bye”都将打印在屏幕上,但浏览器似乎正在等待服务器上的更多内容(Firefox 4和IE6的进度条在这10秒内保持缓慢移动)。

我希望用户(对于我的真实应用程序)相信该过程完全回到基础并且能够完全放心地关闭网页。随着进度条仍在移动,我确信他们会坐下来等待它停止然后关闭它或离开。

只是要清楚 - 过程似乎是背景的。我可以关闭网络浏览器。真正的bacgrouind工作继续运行(有时长达一个小时)没有问题。我想从UI的角度来清理它。

谢谢!

2 个答案:

答案 0 :(得分:1)

你的问题是CGI程序已经完成,但是网络服务器还没有被告知它已经完成,并且在实际向浏览器说明它已经完成之前正在等待它。你需要弄清楚如何沟通,或者想出一个黑客来解决这个问题。以下是一些可能的策略。

  1. 在Unix中,告诉网络服务器现在是时候离开的正确方法是 daemonize 后台进程。有关如何执行此操作的详细信息非常具体。但是,Google Win32 perl daemon的Google搜索引导我Win32::Daemon然后Win32::Service,这可能会帮助您为Windows执行类似操作。我看过没有细节的评论表明这会有效。如果您需要帮助解决这个问题,我建议您前往Perlmonks并询问。 Perl的专业知识比这里更多。

  2. 假设您可以使用某种批处理作业计划程序。然后,您可以只计划要完成的任务,而不是启动作业。任务被选中并运行。如果您需要运行的工作足够密集,以至于您希望它运行在除您的网络服务器之外的某个位置,则此策略特别有用。

  3. 您的CGI脚本可以转向并向Web服务器发出http请求,以便启动作业,它不会等待。这是一个简短的例子,向您展示如何做到这一点:

    #! /usr/bin/perl -w
    use strict;
    use Carp qw(croak);
    use Data::Dumper qw(Dumper);
    use LWP::UserAgent;
    
    my $ua = LWP::UserAgent->new();
    $ua->add_handler(response_header => sub {croak "complete"}, m_code => 200);
    my $response = $ua->get("http://www.perl.com/");
    
    if ($response->is_success) {
        print "Request backgrounded\n";
    }
    else {
        print "Uh, oh.\n";
    }
    

答案 1 :(得分:0)

CGI脚本在标准输出重定向的情况下运行,可以直接连接到TCP套接字或管道。通常,在句柄及其所有副本都关闭之前,连接不会关闭。默认情况下,子进程将继承句柄的副本。

有两种方法可以阻止连接等待子进程。一种是防止子进程继承句柄,另一种是让子进程在启动时关闭其句柄副本。

如果子进程在Perl中,我认为你可以非常简单地关闭句柄:

close(STDOUT);

如果要阻止子进程继承句柄,可以使用SetHandleInformation函数(如果可以访问Win32 API)或在调用CreateProcess时将bInheritHandles设置为FALSE。或者,在启动子进程之前关闭句柄。