如何在 IIS 下的 Perl CGI 中完全后台进程
感谢这里的其他一些精彩帖子(例如这个和),我有几种可靠的方法来在 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 秒内一直缓慢移动)。
我希望用户(对于我的真实应用程序)相信该过程是完全后台的,并且能够完全放心地关闭网页。由于进度条仍在移动,我确信他们会坐下来等待进度条停止,然后再关闭它或导航离开。
需要明确的是 - 该过程似乎是有背景的。我可以关闭网络浏览器。真正的后台作业会继续运行(有时长达一个小时),没有任何问题。我只是想从用户界面的角度清理这个问题。
谢谢!
Thanks to some other great posts here (like this and that), I have several reliable methods to background a process in a Perl script.
However, in my environment (IIS6 on Windows Server 2003), it doesn't seem to completely background. Take this script:
use CGI::Pretty qw(:standard);
print header;
print start_html;
print "hi<br>";
system(1,qw(sleep 10));
print "bye";
print end_html;
The browser will stay "connected" for 10 seconds while the sleep process runs. "hi" and "bye" will both be printed on the screen, but the browser seems to be waiting for something more from the server (Firefox 4's and IE6's progress bars keep moving slowly for those 10 seconds).
I'd like the user (for my real app) to believe the process is fully back-grounded and be fully comfortable being able to close the webpage. With the progress bar still moving, I'm sure they'll sit and wait for it to stop before they close it or navigate away.
Just to be clear - the process appears backgrounded. I can close the web browser. The real background job continues to run (sometimes for up to an hour) with no issues. I'd just like to clean this up from the UI perspective.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
![扫码二维码加入Web技术交流群](/public/img/jiaqun_03.jpg)
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你的问题是CGI程序已经完成,但是网络服务器还没有被告知它已经完成,并且正在等待,然后才真正告诉浏览器它已经完成。您需要弄清楚如何传达这一点,或者想出一个办法来解决这个错误。以下是一些可能的策略。
在 Unix 中,告诉网络服务器该离开的正确方法是守护后台进程。如何执行此操作的详细信息非常特定于 Unix。然而,谷歌搜索
Win32 perl daemon
引导我到 Win32::Daemon 和然后 Win32::Service,它可以帮助您为 Windows 执行类似的操作。我看到没有详细信息的评论表明这会起作用。如果您需要帮助解决这个问题,我建议您去 Perlmonks 并在那里询问。那里有比这里更多的 Perl 特定专业知识。假设您有某种可用的批处理作业调度程序。然后,您可以只安排要完成的任务,而不是启动作业。任务被拾取并运行。如果您需要运行的作业足够密集,以至于您希望它在 Web 服务器之外的其他地方运行,则此策略特别有用。
您的 CGI 脚本可以转身并向网络服务器发出 http 请求以启动作业,但它不会等待。下面是一个简短的示例,向您展示如何执行此操作:
<前><代码>#! /usr/bin/perl -w
使用严格;
使用鲤鱼 qw(croak);
使用 Data::Dumper qw(Dumper);
使用 LWP::UserAgent;
我的 $ua = LWP::UserAgent->new();
$ua->add_handler(response_header => sub {croak "complete"}, m_code => 200);
我的 $response = $ua->get("http://www.perl.com/");
if ($response->is_success) {
print "请求后台\n";
}
别的 {
打印“呃,哦。\n”;
}
Your problem is that the CGI program is done, but the webserver hasn't been told it is done, and is waiting for that before actually saying to the browser that it is done. You'll need to figure out how to communicate that, or else come up with a hack to work around the bug. Here are a few possible strategies.
In Unix the right way to tell the webserver that it is time to go away is to daemonize the background process. The details of how to do this are pretty Unix specific. However Googling for
Win32 perl daemon
lead me to Win32::Daemon and then Win32::Service, which may help you do something similar for Windows. I've seen comments without details suggesting that this will work. If you need help figuring this out, I would suggest going to Perlmonks and asking there. There is more Perl specific expertise there than here.Suppose that you have some sort of batch job scheduler available to you. Then instead of launching a job, you can just schedule a task to be done. The task gets picked up and run. This strategy is particularly useful if the job that you need to run is intensive enough that you'd like it to run somewhere other than your webserver.
Your CGI script can turn around and issue an http request to the webserver for the job to start, which it doesn't wait for. Here is a brief example showing you how to do that:
CGI 脚本在标准输出重定向的情况下运行,直接重定向到 TCP 套接字或管道。通常,在句柄及其所有副本关闭之前,连接不会关闭。默认情况下,子进程将继承句柄的副本。
有两种方法可以防止连接在子进程上等待。一是防止子进程继承句柄,二是让子进程在启动时关闭其句柄副本。
如果子进程在Perl中,我认为你可以非常简单地关闭句柄:
如果你想阻止子进程继承句柄,你可以使用SetHandleInformation函数(如果你有权访问Win32 API)或将bInheritHandles设置为FALSE在对 CreateProcess 的调用中。或者,在启动子进程之前关闭句柄。
CGI scripts are run with standard output redirected, either directly to the TCP socket or to a pipe. Typically, the connection won't close until the handle, and all copies of it, are closed. By default, the subprocess will inherit a copy of the handle.
There are two ways to prevent the connection from waiting on the subprocess. One is to prevent the subprocess from inheriting the handle, the other is for the subprocess to close its copy of the handle when it starts.
If the subprocess is in Perl, I think you could close the handle very simply:
If you want to prevent the subprocess from inheriting the handle, you could use the SetHandleInformation function (if you have access to the Win32 API) or set bInheritHandles to FALSE in the call to CreateProcess. Alternatively, close the handle before launching the subprocess.