我有一个包含长字符串的变量。(具体来说,它包含了几千字节的javascript代码)
我想通过一个外部命令传递这个字符串,在本例中是一个javascript压缩器,并在php中捕获外部命令的输出(压缩的javascript),将其分配给一个变量。
我知道php中有压缩javascript的类,但这只是一般问题的一个例子。
最初我们使用:
$newvar = passthru("echo $oldvar | compressor");
这适用于小字符串,但不安全。(如果oldvar包含对shell有特殊意义的字符,那么任何事情都可能发生)
使用escapeshellarg转义修复了这个问题,但是由于操作系统对最大允许参数长度的限制,解决方案不能用于更长的字符串。
我尝试使用popen("command" "w")
并写入命令-这有效,但命令的输出默默地消失在空白中。
$newvar = external_command($oldvar);
使用proc_open-function,您可以获得进程的标准输出和标准输入的句柄,从而将数据写入该进程并读取结果。
使用rumpels的建议,我能够设置以下解决方案,似乎工作得很好。把它贴在这里,以方便其他对这个问题感兴趣的人。
public static function extFilter($command, $content){
$fds = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w") // stderr is a pipe that the child will write to
);
$process = proc_open($command, $fds, $pipes, NULL, NULL);
if (is_resource($process)) {
fwrite($pipes[0], $content);
fclose($pipes[0]);
$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);
$return_value = proc_close($process);
// Do whatever you want to do with $stderr and the commands exit-code.
} else {
// Do whatever you want to do if the command fails to start
}
return $stdout;
}
可能存在死锁问题:如果您发送的数据比管道的总大小大,那么外部命令将阻塞,等待有人从它的标准输出中读取,而php被阻塞,等待从标准输出中读取以便为更多输入腾出空间。
可能PHP会以某种方式处理这个问题,但是如果您计划发送(或接收)比管道适合的数据更多的数据,则值得测试一下。