2011-04-04 51 views
1

感谢这里的其他一些很棒的帖子(如thisthat),我有几个可靠的方法来在Perl脚本中背景进程。如何在IIS下完成Perl Perl CGI的后台进程背景信息

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

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

浏览器将保持,而睡眠过程中运行,持续10秒“连接”。 “嗨”和“再见”都将被打印在屏幕上,但浏览器似乎在等待更多来自服务器的东西(Firefox 4和IE6的进度条在这10秒内保持缓慢移动)。

我想用户(我的真正的应用程序),相信这个过程是完全恢复接地和完全舒适的能够关闭的网页。随着进度条的移动,我相信他们会坐下来等待它停下来,然后再关闭它或走开。

只要是明确的 - 过程中出现中背景。我可以关闭网页浏览器。真正的bacgrouind作业继续运行(有时长达一个小时),没有问题。我只想从UI的角度来清理它。

谢谢!

回答

1

你的问题是,CGI程序已完成,但Web服务器没有被告知这是做了,居然说要它做的浏览器之前等待的。你需要弄清楚如何沟通,或者想出解决问题的办法。以下是一些可能的策略。

  1. 在Unix中告诉网络服务器,它是时候离开是为了守护进程后台进程的正确途径。如何做到这一点的细节是非常特定于Unix的。但谷歌搜索Win32 perl daemon导致我Win32::Daemon然后Win32::Service,这可能会帮助你做一些类似的Windows。我看过没有任何细节的评论,暗示这会起作用。如果你需要帮助解决这个问题,我会建议去Perlmonks并在那里询问。这里有比Perl更多的Perl专业知识。

  2. 假设你有某种批处理作业调度器提供给您。然后,而不是启动一项工作,您可以安排一项任务完成。任务被拿起并运行。如果您需要运行的工作足够密集,以至于您希望它运行在除web服务器以外的其他位置,则此策略特别有用。

  3. 您的CGI脚本可以转身向网络服务器发出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"; 
    } 
    
+0

感谢您的建议。关于选项:1)对于这个特定的小UI“nit”的解决方案太复杂; 2)绝对考虑它,但我们有足够的计划任务运行在这台服务器上,我讨厌添加另一个只是投票工作要完成; 3)这非常有趣,几乎就像一个单向的Web服务 - 谢谢! – jimtut 2011-04-04 17:59:20

+1

服务实际上是您在Windows上可以背景的唯一方式,因为它的流程模型不允许将流程从父级分离并独立运行。但是我们发现使用Windows资源工具包工具instsrv.exe和srvany.exe更容易,这使得将Perl脚本设置为Windows服务相当容易。我们使用这种方法解决了这个问题,并使用类似REST的API对HTTP :: Daemon脚本进行守护进程管理。 – 2011-06-03 21:10:53

+0

@morungos:我的选择3也可以工作,尽管我毫不犹豫地承认它是一种混合物。这项工作并不是真正的背景,但从正在看它的网络浏览器的角度来看,它是。 – btilly 2011-06-03 22:49:59

0

CGI脚本与重定向标准输出上运行,要么直接向TCP套接字或管道。通常情况下,直到句柄及其所有副本都关闭后,连接才会关闭。默认情况下,子进程将继承该句柄的副本。

有防止等待子进程的连接两种方式。一种是防止子进程继承句柄,另一种是当子进程启动时关闭它的副本。

如果子是在Perl,我想你可以关闭处理得很干脆:

close(STDOUT); 

如果你想防止子继承手柄,你可以使用SetHandleInformation功能(如果你有访问Win32 API)或在调用CreateProcess时将bInheritHandles设置为FALSE。或者,在启动子流程之前关闭句柄。

+0

我尝试在Perl CGI和Perl子进程中使用close()方法。恐怕它不起作用,但我赞赏这个建议。对不起,花了这么长的时间来尝试一下! – jimtut 2012-05-31 16:31:33