2012-04-01 41 views
0

Perl脚本需要接收ajax请求,向浏览器发回“成功”消息,然后“产生”一个进程在后台运行。 (这个产生的过程可能需要10分钟才能运行,所以我不希望浏览器等待 - 或发生apache超时)Perl发送ajax响应,然后exec()

我的印象是Perl exec()函数会这样做。比使用fork()或system()更好,因为它们应该等待响应。

但是,脚本似乎在等待exec()程序完成,然后将成功消息发送到浏览器。这里是我的Perl脚本的末尾:

print "Content-type: text/html\n\n"; 
print "success"; # this gets returned via ajax 

exec $script_filename, $var1, $var2, $var3; 

一切正常,但直到$ SCRIPT_FILENAME结束运行浏览器未收到“成功”的消息。

我想要做的似乎与this previous post类似,但是那里没有足够的细节。

任何想法?谢谢。

+0

fork()不会“等待响应”。 – pilcrow 2012-04-02 04:12:28

回答

0

我找到了另一个似乎解决我的问题的StackOverflow问题的答案 - 请参阅Paul Tomblin's response here

看来,如果Perl脚本执行exec(),然后Apache等待。但是,如果perl脚本首先执行fork,然后fork执行exec(),那么一切都按预期工作。

这里是它看起来像在我的代码,替换什么在我原来的职位:

use POSIX 'setsid'; 

$SIG{CHLD} = 'IGNORE'; 

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

my $kpid = fork; 
if ($kpid) 
{ 
    # Parent process 
    print "Content-type: text/html\n\n"; 
    print "success"; # this gets returned via ajax 
} 
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($script_filename, $var1, $var2, $var3) ; 
    } 
    exit 0; 
} 

感谢亚当确认立刻意识到什么,我本来试图做的是有缺陷的。

感谢乔纳森为我指出了正确的方向。

+0

恭喜修复!如果可以,请确保将您的答案标记为“已接受”,以便其他人可以从您的成功中学习。干杯〜 – 2012-04-02 14:58:32

+0

我会的。这让我等了8个小时。 – egret 2012-04-02 18:55:41

2

Apache会在完成对浏览器的响应之前等待脚本完成。您应该安排一项作业在后台运行,然后让脚本终止。

为了安排后台作业,您可以将后台任务处理器实现为一个守护进程,它在执行它们之前通过IPC(例如通过UNIX域套接字)从您的perl脚本接受任务。或者,您可以使用现有的UNIX工具进行后台作业调度,如atbatch。详情请参阅this manpage

如果您需要非常高的可靠性,您可能还需要在向客户端确认任务已安排之前,将任务保留到外部存储器。

+0

+1'Apache将会等待'(但我不太确定其余的)。使用'fork()'并让子进程运行后台进程和父进程(所以Apache停止等待)将解决问题。您不必使用复杂的调度('批处理'或'at'); 'fork()'已经足够了。它可能会有好处;分叉的孩子具有可以简化后台处理的设置的上下文。 – 2012-04-01 19:57:14

+0

你是否在暗示这样的事情:$ SIG {CHLD} ='IGNORE'; defined(my $ kid = fork)或死“不能fork:$!\ n“; 如果($小子){ 打印 ”父已完成\ n“; } 其他{ #做一些耗时 } – egret 2012-04-01 19:59:38

+0

@JonathanLeffler从OP的代码,似乎意图是运行一个外部的命令/脚本,这很容易用at/batch完成,并且确保了更好的隔离(思考信号,进程组,文件描述符等)当需要父脚本的上下文时,fork() – 2012-04-01 20:27:39

相关问题