我有一个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;
}
有什么建议吗?
答案 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命令,但不要求您将所有结果存储在内存中。
或者,您可以先将所有输出存储到本地文件中,然后解析它。