如何在 CGI 中分离线程



我有一个Perl插件,需要一段时间才能完成操作。该插件通常通过 web 从 CGI 界面启动,该界面应该在后台发送并立即打印消息。不幸的是,我找不到一种方法来做到这一点。我的意思是 CGI 正确启动插件,但它也等待它完成,我不想发生。我尝试了 &子、分离,甚至使用 Proc::Background,到目前为止没有运气。我很确定问题与CGI有关,但我想知道为什么,如果可能的话,解决这个问题。这是我尝试过的代码,请记住,所有方法都可以在控制台上运行良好,只是 CGI 产生了问题。

# CGI
my $cmd = "perl myplugin.pl";
# Proc::Background
my $proc = Proc::Background->new($cmd);
# The old friend &
system("$cmd &");
# The more complicated fork
my $pid = fork;
if ($pid == 0) {
    my $launch = `$cmd`;
    exit;
}
# Detach
print "Content-type: text/htmlnn";
print "Plugin launched!";

我知道StackOverflow上有一个类似的问题,但正如你所看到的,它并不能解决我的问题。

这基本上是 shell 在 pilcrow 的答案中幕后所做的事情的 Perl 实现。它有两个潜在的优势,它不需要使用 shell 来调用你的第二个脚本,并且在极少数情况下,它会提供更好的用户反馈,即分叉失败。

my @cmd = qw(perl myplugin.pl);
my $pid = fork;
if ($pid) {
    print "Content-type: text/htmlnn";
    print "Plugin launched!";
}
elsif (defined $pid) {
    # I skip error checking here because the expectation is that there is no one to report the error to.
    open STDIN,  '<', '/dev/null';
    open STDOUT, '>', '/dev/null'; # or point this to a log file
    open STDERR, '>&STDOUT';
    exec(@cmd);
}
else {
    print "Status: 503 Service Unavailablen";
    print "Content-type: text/htmlnn";
    print "Plugin failed to launch!";
}

让子进程关闭或取消其继承的标准输出和标准错误,以便 Apache 知道它可以自由响应客户端。 请参阅梅林关于该主题的文章。

例:

system("$cmd >/dev/null 2>&1 &");

虽然看到system("$cmd ...")我不寒而栗.

最新更新