2011-04-04 50 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