[英]Why is exec() silently discarding bytes?
经过大量的挣扎,我发现了一些我无法解释/解决的行为,所以在这里寻求帮助。 在我们的服务器( Ubuntu 16.04.5 LTS,PHP 7.0.30 )上,我们使用'httpdocs'之外的一些工具,使用exec()
调用它们来获取它们的输出。 在这种情况下,它是QRCode生成器。
但是,某些QR码将不会显示。 我们从工具中获得了一个输出( 输出PNG的数据 ),但当我们将其显示为图像时,它似乎因某种原因而被破坏。
经过大量的调试后我发现结果有时与工具的输出相差1或2个字节。
我使用下面的QR码( 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 和 $输出,但现在我丢失了字节。 我已经尝试了PHP_EOL的一些变体,我们现在使用胶水( \\ n,\\ r和\\ n \\ r ),但是前两个行结尾,我仍然只有239个字节和最后一个,我最终得到241个字节,所以1个字节到很多。
为什么我在这里输掉一个字节? 将$ output-array转换回字符串的正确方法是什么? 有没有办法通过破坏阵列来恢复240字节的输出? 或者还有其他功能我还没有找到执行命令,它会给我输出以及return_var?
根据exec
的手动输入,该函数返回最后一行输出。 最后一行是否也包含在$output
的最后一个元素中尚不清楚。
但更重要的是手册说明:
尾随空格(例如\\ n)不包含在此数组中。
我猜这是数组的每个元素(即输出的每行),但无论哪种方式,你的空白在这里都很重要,因为你没有处理文本 - 所有的字节都很重要而且有意义。 请记住,空白并不仅仅意味着\\n
。 它也可以意味着\\t
或 (例如,一个空格)。
如果一行以F\\t\\n
结尾(大写字母F或任何其他非空白字符,制表符,然后是换行符),则两个空格字符都将从末尾删除。 在进行内implode
操作时,你可能会把\\n
放回去,但你永远不会知道被剥离的\\t
。
这里要实现的关键是exec
期望处理纯文本而不是原始二进制数据 。
我建议不要使用cat qr.png
,而是使用base64 qr.png
将二进制数据编码为ASCII字符串,然后使用base64_decode
在PHP中base64_decode
进行解码。 如果您不打算在现实中使用cat
,您仍然可以通过base64
QR生成命令的输出,如下所示: generate-qr-png |base64
。 在那种情况下不应该有任何重要的空白,所以没有任何东西会被exec
吸引。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.