PHP SSH按模式读取文件块

时间:2012-12-07 20:22:27

标签: php file ssh

我有一个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;
}

有什么建议吗?

2 个答案:

答案 0 :(得分:1)

很难说这是否适合您,但如果日志在文件中,您可以使用phpseclib's SFTP implementation(最新的Git版本)。

例如

如果执行$sftp->get('filename.ext', false, 0, 1000),它将从filename.ext下载字节0-1000并返回包含这些字节的字符串。如果你执行$sftp->get('filename.ext', false, 1000, 1000),它将下载字节1000-2000。

答案 1 :(得分:0)

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

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