3

我有一个包含长字符串的变量。(特别是它包含几千字节的 javascript 代码)

我想通过一个外部命令传递这个字符串,在这种情况下是一个 javascript 压缩器,并在 php 中捕获外部命令(压缩的 javascript)的输出,并将其分配给一个变量。

我知道在 php 中有用于压缩 javascript 的类,但这只是一般问题的一个示例。

最初我们使用:

$newvar = passthru("echo $oldvar | compressor");

这适用于小字符串,但不安全。(如果 oldvar 包含对 shell 具有特殊意义的字符,那么任何事情都可能发生)

使用 escapeshellarg 转义解决了这个问题,但是由于操作系统对最大允许参数长度的限制,解决方案会中断更长的字符串。

我尝试使用popen("command" "w")并写入命令 - 这有效,但命令的输出默默地消失在空白中。

从概念上讲,我只想做相当于:

$newvar = external_command($oldvar);
4

2 回答 2

2

使用proc_open函数,您可以获得进程的标准输出和标准输入的句柄,从而将数据写入其中并读取结果。

于 2011-09-07T10:11:21.343 回答
0

使用 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;
}

可能存在死锁问题:如果您发送的数据大于管道的组合大小,那么外部命令将阻塞,等待有人从它的 stdout 中读取,而 php 被阻塞,等待从中读取 stdin为更多的输入腾出空间。

Possibly PHP takes care of this issue somehow, but it's worth testing out if you plan to send (or receive) more data than fits in the pipes.

于 2011-09-09T05:24:19.023 回答