Perl 如何在CGI中分离线程?

Perl 如何在CGI中分离线程?,perl,background,cgi,fork,detach,Perl,Background,Cgi,Fork,Detach,我有一个Perl插件,需要一段时间才能完成操作。该插件通常通过网络从CGI界面启动,该界面应该在后台发送插件并立即打印消息。不幸的是,我找不到这样做的方法。我的意思是CGI正确地启动插件,但它也会等待插件完成,我不想这样。我试着用&,用叉子,用分离,甚至到目前为止都没有运气。我很确定这个问题与CGI有关,但我想知道原因,如果可能的话,解决这个问题。以下是我尝试过的代码,请记住,所有方法在控制台上都非常有效,只是CGI造成了问题 # CGI my $cmd = "perl myplugin.pl"

我有一个Perl插件,需要一段时间才能完成操作。该插件通常通过网络从CGI界面启动,该界面应该在后台发送插件并立即打印消息。不幸的是,我找不到这样做的方法。我的意思是CGI正确地启动插件,但它也会等待插件完成,我不想这样。我试着用&,用叉子,用分离,甚至到目前为止都没有运气。我很确定这个问题与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/html\n\n";
print "Plugin launched!";

我知道存在堆栈溢出,但正如您所看到的,它并不能解决我的问题。

让您的子进程关闭或复制其继承的标准输出和标准错误,以便Apache知道它可以自由响应客户端。看梅林关于这个问题的报道

例如:

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

虽然看到系统$cmd…

让您的子进程关闭或复制其继承的标准输出和标准错误,我会不寒而栗,这样Apache就知道它可以自由响应客户端。看梅林关于这个问题的报道

例如:

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

尽管看到system$cmd我不寒而栗……

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

my @cmd = qw(perl myplugin.pl);

my $pid = fork;
if ($pid) {
    print "Content-type: text/html\n\n";
    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 Unavailable\n";
    print "Content-type: text/html\n\n";
    print "Plugin failed to launch!";
}

这基本上是一个Perl实现,它实现了pilcrow回答中shell在幕后所做的事情。它有两个潜在的优势,它不需要使用shell来调用第二个脚本,并且在fork失败的罕见情况下,它提供了更好的用户反馈

my @cmd = qw(perl myplugin.pl);

my $pid = fork;
if ($pid) {
    print "Content-type: text/html\n\n";
    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 Unavailable\n";
    print "Content-type: text/html\n\n";
    print "Plugin failed to launch!";
}

到目前为止没有运气意味着什么?你有错误吗?什么错误?您知道是否正在执行perl myplugin.pl吗?你怎么知道呢?到目前为止没有运气,我的意思是它会等待myplugin.pl完成。插件正在执行,这不是问题所在。非常基本的$cmd&对我有效,即CGI程序不会等待myplugin.pl完成。提供有关CGI执行环境及其配置的更多详细信息。请注意,您需要向提供足够的信息。这可能很难,因为到目前为止,我唯一能提供的信息是CGI正在Apache上运行。到目前为止,运气不佳意味着什么?你有错误吗?什么错误?您知道是否正在执行perl myplugin.pl吗?你怎么知道呢?到目前为止没有运气,我的意思是它会等待myplugin.pl完成。插件正在执行,这不是问题所在。非常基本的$cmd&对我有效,即CGI程序不会等待myplugin.pl完成。提供有关CGI执行环境及其配置的更多详细信息。请注意,您需要向提供足够的信息。这可能很难,因为目前我能提供的唯一信息是CGI正在Apache上运行。首先,它非常有效。谢谢:第二,我可以知道您为什么认为该系统是wierd吗?我想提高我的Perl技能,所以请随意解释:我怀疑pilcrow认为这很奇怪。我可能会用“讨厌”这个词。使用一个参数的系统调用中的变量插值可能会导致安全问题。使用系统的列表形式可以防止这种情况发生,但也可以防止shell重定向。@Ven'Tatsu:Ha。使用“令人厌恶”的警告@pilcrow,=我有一种感觉,要实现的补丁可能不会被接受,但也许可以制作一个。首先,它工作得很好。谢谢:第二,我可以知道为什么你们认为这个系统是wierd吗?我想提高我的Perl技能,所以请随意解释:我怀疑pilcrow认为这很奇怪。我可能会用“讨厌”这个词。使用一个参数的系统调用中的变量插值可能会导致安全问题。使用系统的列表形式可以防止这种情况发生,但也可以防止shell重定向。@Ven'Tatsu:Ha。使用“令人厌恶”的警告@pilcrow,=我感觉要实现的补丁可能不会被接受,但也许可以制作一个。+1表示不使用系统。我知道错误检查被省略了,但我仍然建议在执行+1之后使用骰子,因为不使用系统。我知道错误检查被省略了,但我还是建议在那个执行官之后进行死。