2

ユーザーが指定した文字列を取得し、リモートサーバーに SSH で送信し、ファイルを配列に読み取り、文字列を含む要求/応答ブロックを解析してユーザーに返す PHP スクリプトがあります。

PHP はファイル全体を配列に格納しようとしてメモリ不足になるため、この実装は大きなログ ファイルでは機能しません。

サンプルデータ:

*** REQUEST

request line 1
request line 2
request line 3
[...]

*** RESPONSE

response line 2
response line 2
response line 3
[...]
[blank line]

リクエストとレスポンスの長さはさまざまなので、何行になるかはわかりません。

ファイル全体をメモリに保存せずにファイルをチャンク単位で読み取るにはどうすればよいでしょうか?ログからデータの完全な要求/応答ブロックを切り捨てずに常に処理できるようにするにはどうすればよいでしょうか?

私の経験は通常、ファイル全体または配列全体で作業しているため、これについては非常に密集しているように感じます。

これが私の現在のコードです ($search は、ログで探しているユーザー指定の文字列を表しています)。これは、最初にファイル全体を配列に入れています。

$stream = ssh2_exec($ssh, $command);
stream_set_blocking($stream, true);
$data = '';
while($buffer = fread($stream, 4096)) {
    $data .= $buffer;
}
fclose($stream);
$rawlog = $data;

$logline = explode("\n",$rawlog);
reset($logline);
$block='';

foreach ( $logline as $k => $v ) {
    if ( preg_match("/\*\*\* REQUEST",$v) && $block != '') {
        if ( preg_match("/$search/i",$block) ) {
            $results[] = $block;
        }
        $block=$v . "\n";
    } else {
        $block .= $v . "\n";
    }
}
if ( preg_match("/$search/i",$block) ) {
    $results[] = $block;
}

助言がありますか?

4

2 に答える 2

1

これがうまくいくかどうかはわかりませんが、ログがファイルにある場合は、phpseclibのSFTP実装(最新のGitバージョン)を使用できます。

例えば。

これを行う$sftp->get('filename.ext', false, 0, 1000)と、filename.extからバイト0〜1000がダウンロードされ、それらのバイトを含む文字列が返されます。あなたがそうするならば、$sftp->get('filename.ext', false, 1000, 1000)それはバイト1000-2000をダウンロードするでしょう。

于 2012-12-12T02:05:33.257 に答える
0

0 から 99、100 から 199 などの行を取得する tail のようなコマンドを使用できます。これにはより多くの ssh コマンドが必要になりますが、すべての結果をメモリに保存する必要はありません。

または、最初にすべての出力をローカル ファイルに保存し、その後解析することもできます。

于 2012-12-08T12:19:10.080 に答える