我应该禁用缓冲区以在CGI程序中启动后台进程吗?

时间:2009-12-29 16:23:55

标签: perl

在我的Perl / CGI Web应用程序中,我有时需要运行一个漫长的过程,这会使下一页的等待无休止。所以我一直在禁用下面的缓冲区,以便在长进程运行之前发送页面内容。

local $| = 1;
print "Content-type: text/html\n\n";
print $output;
&background_process();

然而,在我看来,缓冲区有其用途,我不应该习惯这样做。有没有更好的方法来运行一个长进程并仍然快速将html返回给客户端?我应该分叉吗?

2 个答案:

答案 0 :(得分:4)

最好的方法是分叉您的流程并将其放在后台。这样,用户离开页面就不会停止,并且页面不会一直处于Web浏览器的加载状态。

答案 1 :(得分:4)

以下是我用来在FastCGI脚本中生成后台进程的一些代码:

$SIG{CHLD} = 'IGNORE';

# This should flush stdout.
my $ofh = select(STDOUT);$| = 1;select $ofh;

my $kpid = fork;
if ($kpid)
{
    # Parent process
    waitpid($kpid, 0);
}
else
{
    close STDIN;
    close STDOUT;
    close STDERR;
    setsid();
    my $gpid = fork;
    if (!$gpid)
    {
        open(STDIN, "</dev/null") ;
        open(STDOUT, ">/dev/null") ;
        open(STDERR, ">/dev/null") ;
        # Child process
        exec($pgm, @execargs) ;
    }
    exit 0;
}

这里有几个重点:

  • 我忽略了SIGCHLD,这是信号 当你的孩子进行治疗时你会得到 退出。
  • 我刷新STDOUT,因此网页浏览器获取整个页面。
  • 我叉两次以确保即使我正在尝试生成的进程仍在运行,Web服务器也能够退出。
  • 我重定向所有标准文件描述符,以确保孙子进程与父进程完全分离。