我有一个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 ...")
我不寒而栗.