2011-04-25 60 views
1

我有一个网页向cgi脚本发送请求,该脚本基本上必须tar和压缩可能超过50G的巨大目录。我在我的cgi脚本中派生了一个进程,用于执行tarling任务,同时向父母脚本中的网页发送响应消息。但是,父脚本(即使没有waitpid($ pid,0))等待焦油过程结束,然后将味精发送到网页,然后通过警告框打印。有没有一种方法可以立即发送msg,以便用户知道tarling过程已经启动,并且该进程可以在后台进行。我不想执行exec(),因为我需要在创建此tar时捕获任何错误球。如何同时运行子进程和父进程

另外,会不会有任何记忆的问题,而我试图焦油这么大的目录?

$SIG{CHLD} = 'IGNORE'; 
$|++; 
$pid = fork(); 
if($pid){ sendResponse($data); exit; } 
elsif($pid == 0) 
{ 
    setsid(); 
    $gpid = fork(); 
    if(! $gpid) 
    { 
     qx(tar up big directories over 50G...); 
    } 
} 

回答

2

您最初的“身份”响应客户端可能正在某个地方缓冲。如果CGI执行是正确设计,无缓冲输出流或者请求刷新一个流应该导致所有的数据包被发送到客户端(它们可能被接收到的任何内容缓冲,但这是你无法控制的)。

请参阅Perl FAQ How do I flush/unbuffer an output filehandle? Why must I do this?了解如何不缓冲您的初始响应。

请注意,CGI环境也可能调用waitpid()或类似的方法,这就是为什么直到子进程存在之后才能看到结果的原因。如果您希望子进程在请求或客户端消失后继续存在,则需要将子进程与父进程关联。请参阅perlipc中的Complete Dissociation of Child from Parent

由于您将要处理的数据量非常大(50G),这需要相当长的时间。很可能客户端或服务器在等待tar结束时可能会遇到某种超时。为了避免这种情况,您可以确保客户端和服务器都疯狂地长时间超时,或者在两者之间定期发送数据以保持连接/请求处于活动状态。您可能需要考虑让tar进程解除关联并让客户端周期性地向服务器查询结果。最后,假设tar不写入内存缓冲区,它应该是相对高效的内存(假设现代硬件)。但是,它可能会消耗大量的CPU和I/O。我肯定会对服务的安全性和潜在的(无意的)拒绝服务保持谨慎。

+0

谢谢!所以,如果我取消缓冲文件句柄($ |),我应该能够立即发送响应。客户端和服务器之间没有数据交换,除了这个msg。为了避免在客户端打印'超时'消息,分离孩子是否明智? – Wilderness 2011-04-25 23:19:59

+0

如果父母和孩子之间没有数据交换,也没有父母徘徊的理由,那么分离就有意义。 此外,在父母关闭时(假设孩子被分离),任何输出都应发送给客户。所以,如果解除关联孩子,你不需要缓存标准输出。 – IndyGreg 2011-04-26 00:48:59

+0

完美!万分感谢 !将尝试一下。 – Wilderness 2011-04-26 01:41:18