【发布时间】:2012-08-27 03:43:07
【问题描述】:
我经常需要在一个目录中搜索服务器日志文件,该目录可能包含 50 个或更多文件,每个文件超过 200 MB。我在 Powershell 中编写了一个函数来执行此搜索。它查找并提取给定查询参数的所有值。它适用于单个大文件或一组小文件,但完全适用于上述情况,即大文件目录。
该函数接受一个参数,该参数由要搜索的查询参数组成。
在伪代码中:
Take parameter (e.g. someParam or someParam=([^& ]+))
Create a regex (if one is not supplied)
Collect a directory list of *.log, pipe to Select-String
For each pipeline object, add the matchers to a hash as keys
Increment a match counter
Call GC
At the end of the pipelining:
if (hash has keys)
enumerate the hash keys,
sort and append to string array
set-content the string array to a file
print summary to console
exit
else
print summary to console
exit
这是文件处理的精简版。
$wtmatches = @{};
gci -Filter *.log | Select-String -Pattern $searcher |
%{ $wtmatches[$_.Matches[0].Groups[1].Value]++; $items++; [GC]::Collect(); }
我只是在使用一种旧的 perl 技巧,通过将找到的项目设为哈希键来对它们进行重复数据删除。也许,这是一个错误,但处理的典型输出最多约为 30,000 个项目。更常见的是,找到的项目在数千个范围内。据我所知,散列中的键数不会影响处理时间,而是文件的大小和数量会破坏它。我最近绝望地扔了GC,它确实有一些积极的影响,但它是微不足道的。
问题在于,对于大型文件的大量集合,处理过程会在大约 60 秒内将 RAM 池吸干。有趣的是,它实际上并没有使用很多 CPU,但是有很多易失性存储正在进行。一旦 RAM 使用率上升 90% 以上,我就可以打卡出去看电视了。完成处理以生成具有 15,000 或 20,000 个唯一值的文件可能需要数小时。
我想要提高效率的建议和/或建议,即使这意味着使用不同的范例来完成处理。我带着我所知道的去了。我几乎每天都使用这个工具。
哦,我致力于使用 Powershell。 ;-) 这个函数是我为我的工作编写的完整模块的一部分,因此,Python、perl 或其他有用语言的建议在这种情况下没有用。
谢谢。
mp
更新:
使用 latkin 的 ProcessFile 函数,我使用以下包装器进行测试。他的功能比我原来的快几个数量级。
function Find-WtQuery {
<#
.Synopsis
Takes a parameter with a capture regex and a wildcard for files list.
.Description
This function is intended to be used on large collections of large files that have
the potential to take an unacceptably long time to process using other methods. It
requires that a regex capture group be passed in as the value to search for.
.Parameter Target
The parameter with capture group to find, e.g. WT.z_custom=([^ &]+).
.Parameter Files
The file wildcard to search, e.g. '*.log'
.Outputs
An object with an array of unique values and a count of total matched lines.
#>
param(
[Parameter(Mandatory = $true)] [string] $target,
[Parameter(Mandatory = $false)] [string] $files
)
begin{
$stime = Get-Date
}
process{
$results = gci -Filter $files | ProcessFile -Pattern $target -Group 1;
}
end{
$etime = Get-Date;
$ptime = $etime - $stime;
Write-Host ("Processing time for {0} files was {1}:{2}:{3}." -f (gci
-Filter $files).Count, $ptime.Hours,$ptime.Minutes,$ptime.Seconds);
return $results;
}
}
输出:
clients:\test\logs\global
{powem} [4] --> Find-WtQuery -target "WT.ets=([^ &]+)" -files "*.log"
Processing time for 53 files was 0:1:35.
感谢所有 cmets 和帮助。
【问题讨论】:
-
如果您最终去一个 powershell 专家站点来解决这个问题,请在此处发布您的最终解决方案(并接受它以获得代表点!)。有趣的问题(对不起,我建议使用 shell 工具:->)。祝你好运。
-
我在Python中做过这种处理,实际上我为它写了一个lib。使用 Python 时,我遇到了相反的问题,它占用了 CPU。专用的二进制工具可能是最好的解决方案,但我只是喜欢编写脚本。避免 CPU/存储问题并非易事。谢谢。
标签: powershell full-text-search