我有一个程序可以从stdin
读取JSON请求,我想在PHP中调用它。
这就是我现在所拥有的
<?php
echo exec(
'echo \''.json_encode($_POST,JSON_NUMERIC_CHECK).'\' | '.
'program'
);
?>
这有效,但是有没有更直接的方法在stdin
中将字符串放入PHP?
可能与pipe(json_encode($_POST,JSON_NUMERIC_CHECK),'program')
相似吗?
在这种情况下,我所拥有的可能很好,但是如果我需要代替二进制数据而不是JSON,该怎么办?如果太长而无法放入shell参数或包含单引号怎么办?
修改:
按照miken32的建议,我这样使用proc_open()
:
$proc = proc_open(
'LD_LIBRARY_PATH=/foo/bar/lib program args',
array(0 => array('pipe','r'), 1 => array('pipe','w')),
$pipes,
NULL
//, array('LD_LIBRARY_PATH','/foo/bar/lib')
);
if (is_resource($proc)) {
fwrite($pipes[0],json_encode($_POST,JSON_NUMERIC_CHECK));
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
proc_close($proc);
}
?>
但是我必须在命令参数中添加LD_LIBRARY_PATH=/foo/bar/lib
。 $env
参数似乎无效。有人知道为什么吗?
答案 0 :(得分:1)
您可以使用popen()
创建到流程的管道:
<?php
$data = json_encode($_POST, JSON_NUMERIC_CHECK);
$p = popen("program", "w");
fwrite($p, $data . PHP_EOL);
$exit_code = pclose($p);
如果您需要从程序中获取数据,则会涉及更多事情,而您需要使用proc_open()
。
<?php
$data = json_encode($_POST, JSON_NUMERIC_CHECK);
$fds = [
0=>["pipe", "r"], // STDIN
1=>["pipe", "w"], // STDOUT
2=>["pipe", "w"], // STDERR
];
$dir = "/path/to/working/directory";
$env = [
"PATH" => "/usr/local/foo/bin:/usr/local/bin:/usr/bin",
"LD_LIBRARY_PATH" => "/usr/local/foo/lib/",
];
$p = proc_open("program", $fds, $pipes, $dir, $env);
fwrite($pipes[0], $data . PHP_EOL);
fclose($pipes[0]);
$return = stream_get_contents($pipes[1]);
$err = stream_get_contents($pipes[2]);
fclose($pipes[1]);
fclose($pipes[2]);
$exit_code = proc_close($p);
if ($exit_code == 0) {
// successful return
echo $return;
} else {
// error
echo "ERR: $err";
}