PHP:管道和passthru混合和匹配外部Linux程序(与STDIN和STDOUT)作为组件

时间:2015-11-20 00:08:25

标签: php

我是一名PHP初学者。我想调用一个外部Unix命令,将一些东西输入其中(例如,字符串和文件),并将结果显示在我的输出缓冲区(浏览器)中。

请考虑以下事项:

echo '<h1>stuff for my browser output window</h1>';
$fnmphp= '/tmp/someinputfile';
$sendtoprogram = "myheader: $fnmphp\n\n".get_file_contents($fnmphp);
popen2outputbuf("unixprogram < $sendtoprogram");
echo '<p>done</p>';

更好的解决方案是让PHP编写myheader(进入Unix程序),然后将文件管道$fnmphp(进入Unix程序);并且unixprogram的输出会立即进入我的浏览器输出缓冲区。

我不认为PHP使用stdout,因此我的Unix程序STDOUT输出将进入浏览器。否则,如果我使用system(),则会发生默认情况。我只能想到需要编写临时文件的解决方案。

我想我站在这里(德语成语;电线交叉)---这可能有一个明显的解决方案。

更新

这是我想要替换的完全不优雅但非常精确的解决方案:

function pipe2eqb( $text ) {
        $whatever= '/tmp/whatever-'.time().'-'.$_SESSION['uid'];
        $inf = "$whatever.in";
        $outf= "$whatever.out";
        assert(!file_exists($inf));
        assert(!file_exists($outf));    
        file_put_contents($inf, $text);
        assert(file_exists($inf));
        system("unixprog < $inf > $outf");
        $fo= file_get_contents($outf);
        unlink($infilename);
        unlink($outfilename);
        return $fo;
}

很容易更换输入或输出,但我想更换两者。我想出来的时候会发布一个解决方案。

1 个答案:

答案 0 :(得分:2)

最好这样做是proc_open函数系列

<?php
$descriptorspec = array(
   0 => array("pipe", "r"),  // stdin 
   1 => array("pipe", "w"),  // stdout 
   2 => array("pipe", "w") // stderr
);
$cwd = NULL;//'/tmp';
$env = NULL;//array();
$cmd='unixprog ';
$process = proc_open($cmd, $descriptorspec, $pipes, $cwd, $env);
assert(false!==$process);

现在,为了给unixprog提供参数,请点击

$cmd='unixprog --arg1='.escapeshellarg($arg1).' --arg2='.escapeshellarg($arg2);

与程序的stdin交谈,喜欢

assert(strlen($stdinmessage)===fwrite($pipes[0],$stdinmessage));

从进程的标准输出读取,喜欢

$stdout=file_get_contents($pipes[$1])

从流程的stderr读取,喜欢

$stderr=file_get_contents($pipes[$2])

检查程序是否已完成,请执行

$status=proc_get_status($process);
if($status['running']){echo 'child process is still running.';}

检查进程完成后的返回代码,

echo 'return code from child process: '.$status['exitcode'];

等待子进程完成,你可以做

while(proc_get_status($process)['running']){sleep(1);}

这是一种快速简便的方法,但它不是最佳选择。 tl; dr:它可能很慢或浪费cpu。长版:  有一些最佳的事件驱动方式来做到这一点,但我不知道该怎么做。想象必须运行程序10次,但程序在100毫秒内执行。这段代码会用10秒!而最佳代码只使用1秒。你可以使用usleep()微秒,但它仍然不是最优的,想象一下如果你每100微秒检查一次,但程序使用10秒执行:你会浪费cpu,检查状态100,000次,而最佳代码只会检查一次..我确定有一种奇特的方式让PHP睡眠,直到进程完成一些回调/信号,也许与stream_select,但我还没有解决它。 (如果有人有解决方案,请告诉我!)

- 在http://php.net/manual/en/book.exec.php

了解详情