如何同时捕获背景PHP进程的PID和输出?

时间:2010-07-16 21:05:38

标签: php bash

我有一个PHP脚本必须使用exec在后台启动第二个脚本。父脚本需要捕获此新进程的PID,但我还需要捕获子脚本的任何潜在输出,以便可以将其记录在数据库中。我不能让子脚本日志记录到数据库,因为我还需要捕获致命错误或任何可能表明脚本有问题的内容。使用PID是因为父进程需要能够检查子进程并查看它何时完成。子进程有时作为crons运行,因此分叉也不是一种选择。如果有问题,我不想要两个执行路径进行调试。

这是我的第一个解决方案,它可以捕获输出,但无法获得正确的PID。

// RedirectToLog.php just reads stdin and logs it to the databse.
$cmd="php child.php </dev/null 2>&1 | php RedirectToLog.php >/dev/null 2>&1 & echo $!";

这里的问题是$!是在后台启动的最后一个进程的PID,最后是RedirectToLog.php而不是child.php。

我的另一个想法是尝试使用FIFO文件(管道)。

$cmd1="php RedirectToLog.php </tmp/myFIFO >/dev/null 2>&1 &"
$cmd2="php child.php </dev/null >/tmp/myFIFO 2>&1 & echo $!"

这个没有用,因为我无法让RedirectToLog可靠地使用fifo,当它发生时,有时候child.php无法将EOF写入管道,这使得两端都在等待另一个并且两个进程都会挂起直到有人被杀。

3 个答案:

答案 0 :(得分:1)

我认为你需要使用
proc_open&amp;
proc_get_status

答案 1 :(得分:1)

使用proc_open在启动进程时获得完整的fd连接。获取proc_open返回的资源并使用proc_get_status获取pid。

$descriptors = array( ... ); // i suggest you read php.net on this
$pipes = array();
$res = proc_open($cmd,$descriptors,$pipes);

$info = proc_get_status($res);
echo $info['pid'];

我还没有完全掌握你所有的问题,但这应该让你开始。

答案 2 :(得分:1)

我猜你真正想要捕获孩子的唯一原因是PID是监视它。如果是这样,可能更容易使用proc_open。这样你就可以基本上打开stdin,stdout和stderr的文件句柄,并监视父节点的所有内容。