在php中连接进程管道

时间:2012-08-29 14:14:00

标签: php resources stream pipe proc-open

我希望使用proc_open创建的一个进程的输出通过管道传输给另一个用proc_open创建的进程(在php中)。例如。在bash我可以这样做:

[herbert@thdev1 ~]$ cat foo
2
3
1
[herbert@thdev1 ~]$ cat foo | sort
1
2
3
[herbert@thdev1 ~]$ 

我想在php中使用proc_open(而不是shell_exec)来模拟这个,以便控制返回代码,管道等。所以我想要这样的东西:

$catPipes=array();
$sortPipes=array();
$cwd = '/tmp';
$env = array();
$catProcess = proc_open("cat foo", array(
        0 => array("pipe", "r"),
        1 => array("pipe", "w")
    ), $catPipes, $cwd, $env);

$sortProcess = proc_open("sort", array(
    0 => array("pipe", "r", $catPipes[1]),
    1 => array("pipe", "w"),
    ), $sortPipes, $cwd, $env);

echo stream_get_contents($sortPipes[1]);
fclose($sortPipes[1]);
//proc_close(this) ... proc_close(that) ... etc

有人知道我怎么能模拟“|” php中的bash,即将cat-process的第二个描述符连接到sort-process的第一个描述符?任何帮助,将不胜感激!但请不要将我重定向到shell_exec,因为我希望能够检查退出代码并记录错误:)。

编辑:

我的工作 - 业务解决方案btw是:

while(!feof($searchPipes[1])) fwrite($lookupPipes[0], stream_get_line($searchPipes[1], 40000));

这基本上就是操作系统会做的事情,但我不想自己管道管理,因为我有一个内核/ posix,而且说实话,它不是1976年:)

1 个答案:

答案 0 :(得分:2)

是的,你可以 - 但我认为你必须这样定义。你可以使用“排序”的STDIN作为“cat”的STDOUT管道。看看下面的内容,对我有用:

<?php

$txt = "a\nc\ne\nb\nd\n";
$fh  = fopen('data://text/plain;base64,' . base64_encode($txt), 'r');

$sort_pipes = array();
$sort_proc  = proc_open(
    'sort',
    array(
        array('pipe', 'r'),
        STDOUT
    ),
    $sort_pipes
);

$cat_pipes = array();
$cat_proc  = proc_open(
    'cat',
    array(
        $fh,
        $sort_pipes[0]
    ),
    $cat_pipes
);

在前两行中,我从文本字符串中定义了一个数据流,我不必依赖文件系统中的某个文件。请注意,我有一个存储在数据流(a,c,e,b,d)中的未排序字符列表。运行上面的脚本应该将一个排序列表返回给STDOUT。

注意,您也可以将资源指定为描述符。在这种情况下,您必须省略数组表示法,因此:

STDOUT

而不是

array(STDOUT)

顺便说一下:您甚至可以直接写入文件名指定的文件。您可以在http://en.php.net/manual/de/function.proc-open.php

的proc_open手册条目中找到有关描述符规范的更多信息

修改

另一种方式当然也有效:您还可以将“cat”写入STDOUT管道array('pipe', 'w')并使用$cat_pipes[1]作为STDIN进行“排序”。 :)