2

我有一个 PHP 脚本,它接受用户提供的字符串,然后通过 SSH 连接到远程服务器,将文件读入数组,然后解析出包含字符串的请求/响应块以返回给用户。

此实现不适用于大型日志文件,因为 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

您可以使用 tail 之类的命令来获取从 0 到 99、从 100 到 199 等的行。这将需要更多 ssh 命令,但不需要您将所有结果存储在内存中。

或者,您可以先将所有输出存储到本地文件中,然后对其进行解析。

于 2012-12-08T12:19:10.080 回答