2011-09-28 51 views
1

我想用popen在后台运行一个php脚本。但是,我需要传递一个(相当大)的序列化对象。PHP管道进入后台进程

$cmd = "php background_test.php >log/output.log &"; 
$fh = popen($cmd, 'w'); 
fwrite($fh, $data); 
fclose($fh); 
//pclose($fh); 

没有&符此代码执行得很好,但父脚本将等待,直到孩子完成运行。使用&符STDIN不获取数据。

任何想法?

回答

0

据我所知,没有办法在PHP发送后台进程并继续提供其STDIN(但也许我错了)。您这里有另外两个选择:

  1. 重构您background_test.php从命令行得到它的输入和改变你的命令行中php background_test.php arg1 arg2 ... >log/output.log &
  2. 如果你的输入很长,写入到一个临时文件,然后喂background_test.php脚本与该文件,如以下代码

示例点2:

<? 
$tmp_file = tempnam(); 
file_put_content($tmp_file, $data); 
$cmd = "php background_test.php < $tmp_name > log/output.log &"; 
exec($cmd); 
1

你可以尝试让子进程写数据和主脚本继续正常。

像这样的事情

// Fork a child process 
$pid = pcntl_fork(); 

// Unable to fork 
if ($pid == -1) { 
    die('error'); 
} 

// We are the parent 
elseif ($pid) { 

    // do nothing 
} 

// We are the child 
else { 

    $cmd = "php background_test.php >log/output.log"; 
    $fh = popen($cmd, 'w'); 
    fwrite($fh, $data); 
    fclose($fh); 
    exit(); 
} 


// parent will continue here 
// child will exit above 

了解更多关于在这里:​​https://sites.google.com/a/van-steenbeek.net/archive/php_pcntl_fork

还要检查功能pcntl_waitpid()(僵尸消失)PHP文档。

+0

提到真的小心僵尸进程,如果你将要分叉脚本。另一种可能的选择是像Gearman这样的队列管理器。 –

+0

好点,加入了waitpid的参考 –

0

使后台进程侦听套接字文件。然后从PHP打开套接字文件并将您的序列化数据发送到那里。当您的后台守护进程通过套接字接收连接时,使其分叉,读取数据然后处理。

你需要做一些阅读,但我认为这是实现这一目标的最好方法。通过套接字我的意思是unix套接字文件,但你也可以在网络上使用它。

http://gearman.org/也是一个不错的选择,因为通过@Joshua