3

多くの苦労の末、説明/解決できない動作を見つけたので、ここに助けを求めます. 私たちのサーバー ( PHP 7.0.30 を搭載した Ubuntu 16.04.5 LTSexec() ) では、出力を取得するためにusing と呼ばれる「httpdocs」以外のいくつかのツールを使用しています。この場合、それは QRCode-generator です。

ただし、一部の QR コードは表示されません。ツールからの出力(PNG のデータを出力)を得たのですが、それを画像として表示すると、何らかの理由で壊れているように見えます。

多くのデバッグを行った後、結果がツールの出力と 1 ~ 2 バイト異なる場合があることがわかりました。

以下の QR コード ( 12345 ) を使用して最後のデバッグを行いました。これは 240 バイトのファイルです。しかし、最終的に出力すると、長さが 239 バイトのように見えるので、どこかで 1 バイトを失ったのでしょうか。

QRコードの例

を使用して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 $output が返されましたが、今ではバイトが失われています。私はすでに PHP_EOL のいくつかのバリアントを試しました。現在は接着剤 ( \n、\r および \n\r ) として使用していますが、最初の 2 つの行末ではまだ 239 バイトしか得られず、最後のものでは、最終的に 241 バイトになるので、1 バイトが多すぎます。

ここでバイトを失うのはなぜですか?$output-array を文字列に戻す正しい方法は何ですか? 配列を内破して 240 バイトの出力を戻す方法はありますか? または、出力と return_var を返すコマンドを実行するためにまだ見つけていない他の関数がありますか?

4

1 に答える 1

2

の手動エントリによるとexec、関数は出力の最後の行を返します。その最後の行が の最後の要素としても含まれているかどうか$outputは不明です。

しかし、もっと重要なことは、マニュアルには次のように記載されています。

\n などの末尾の空白は、この配列には含まれません。

これは配列の要素ごと(つまり、出力の行ごと)だと思いますが、いずれにせよ、テキストを扱っていないため、ここでは空白が重要になります-ここではすべてのバイトが重要で意味があります. 空白は単なる意味ではないことを覚えておいてください\n。たとえば、\tまたは(スペース)を意味することもあります。

行がF\t\n(大文字の F、またはその他の非空白文字、タブ、改行) で終わる場合、両方の空白文字が末尾から削除されます。手術をするときimplode、背中をつけているかもしれませんが、それが剥がれ\nたことを知ることは決してありません.\t

ここで重要なことは、exec生のバイナリ データではなくプレーン テキストを処理することを期待していることです。

を使用する代わりにcat qr.png、 を使用base64 qr.pngしてバイナリ データを ASCII 文字列にエンコードし、PHP で を使用してデコードすることをお勧めしますbase64_decode。実際に使用しない場合でも、次のようcatに QR 生成コマンドの出力をパイプすることができます。そのような状況では重要な空白があってはならないので、 によって何も変更されません。base64generate-qr-png |base64exec

于 2018-07-30T21:46:45.533 に答える