【发布时间】:2019-01-07 04:52:55
【问题描述】:
经过一番挣扎,我发现了一些我无法解释/解决的行为,所以在这里寻求帮助。在我们的服务器(Ubuntu 16.04.5 LTS 和 PHP 7.0.30)上,我们正在使用“httpdocs”之外的一些工具,这些工具使用 exec() 调用以获取它们的输出。在这种情况下,它是一个二维码生成器。
但是,某些 QR 码不会显示。我们从该工具获得了一个输出(输出 PNG 的数据),但是当我们将其显示为图像时,它似乎由于某种原因被破坏了。
经过大量调试,我发现结果有时与工具的输出相差 1 或 2 个字节。
我使用下面的二维码 (12345) 进行了最后一次调试,这是一个 240 字节的文件。但是,最终输出时,长度似乎是239字节,所以我们在某个地方丢失了一个字节?
我发现使用exec(),我们正在创建一个输出数组。此数组中不包含尾随空格,例如 \n,因此 implode() 将数组粘合回字符串,如下所示:
<?php
$cmd = 'cat qr.png';
$output = array();
$exit_code = 0;
exec($cmd, $output, $exit_code);
if($exit_code === 0)
{
header ("Content-type: image/png;");
print implode(PHP_EOL, $output);
}
die();
但是由于某种原因,在这个过程中丢失了一个字节?我已经使用shell_exec() 尝试了一些其他解决方案(但这里没有 return_var,所以我们无法检查验证过程......)
<?php
$command = 'cat qr.png';
$output = shell_exec($command);
if($output !== null)
{
header ("Content-type: image/png;");
print $output;
}
die();
...并使用passthru()(但是这会直接输出内容,这是不希望的。在实际代码中不可能像下面的示例中那样输出缓冲...)
<?php
$command = 'cat qr.png';
$return_var = 0;
ob_start();
passthru($command, $return_var);
if($return_var === 0)
{
header ("Content-type: image/png;");
$output = ob_get_clean();
print $output;
}
die();
到目前为止,exec()-函数对我们来说一直运行良好,导致 $return_var AND $ 输出,但现在我正在丢失字节。我已经尝试了 PHP_EOL 的一些变体,我们现在将其用作胶水(\n、\r 和 \n\r),但对于前 2 个行尾,我仍然只有 239字节和最后一个字节,我最终得到 241 个字节,所以 1 个字节很多。
为什么我在这里丢失了一个字节?将 $output-array 转换回字符串的正确方法是什么?有没有办法通过内爆数组来取回 240 字节的输出?或者还有其他我还没有找到的函数来执行一个可以给我输出和 return_var 的命令?
【问题讨论】:
-
我强烈怀疑与行尾相关的一些时髦的事情正在发生。您是否将收到的损坏文件与正确的文件进行了比较?另外,readfile 呢?
-
字符编码有区别吗?行尾实际上是一样的吗?您是否还尝试查找文件中的任何差异?还;如果图像完全相同,您可能不想在二进制级别上花费太多时间进行调试。
-
使用 hex-viewer 工具检查这 2 个文件可以为您提供丢失字节的线索。是换行吗?在开始时?在末尾?除了这个字节之外,这两个文件是否相同?
-
在这种情况下,命令是
cat qr.png,但在最终的解决方案中,这类似于/usr/local/bin/tools/generate-qr --input="12345",因此readfile 将不起作用。编码是相同的,但我在某处缺少行尾。区分文件时,我在工作文件(第 3 行)中看到一个倒置的问号,但在损坏的输出中丢失了。当使用 PHP 中的 ord() 时,将倒置的问号粘贴到字符串中,它告诉我它的值是 13 (Enter?)....所以这是我在 exec() 中缺少的换行符,但是怎么做我能正确找回吗? -
很抱歉,我无法了解这里发生了什么。在使用换行符作为
Content-type: image/png;进行内爆后,如何将命令行输出发送到客户端?您的工具是在命令行中以▄█▄ 之类的符号形式将二维码生成为文本输出,还是生成图像二进制文件并将其保存在文件系统中?
标签: php exec shell-exec implode passthru