[英]efficiency and speed increase of invoke-parallel -scriptblock
是否有一種方法可以加快此命令的速度並使其更有效地使用資源?
如果文件不必提取且可以通過evtx文件格式解析,我願意轉換為python 3.5。
我有一個腳本,我正在使用帶有腳本塊的cmdlet invoke-parallel運行。 $ files是我根據用戶名和事件ID過濾的10000個evtx文件的列表。
我試圖調用powershell.exe的新實例並從腳本塊運行get-winevent cmdlet,但這會實例化到許多進程而不會關閉。 我沒有嘗試過工作,但是不確定在這種情況下該在哪里進行。
$files | Invoke-Parallel -ImportModules -ScriptBlock{
Get-WinEvent -FilterHashtable @{Path=$_;id=4624;data="ANONYMOUS LOGON","user.name1", "user.name2" } |
Select-Object -Property MachineName,RecordId, TimeCreated,Id,
@{Name="SubjectUserSid"; Expression={$_.Properties[0].Value}},
@{Name="SubjectUserName";Expression={$_.Properties[1].Value}},
@{Name="SubjectDomainName";Expression={$_.Properties[2].Value}},
@{Name="SubjectLogonId";Expression={$_.Properties[3].Value}},
@{Name="TargetUserSid";Expression={$_.Properties[4].Value}},
@{Name="TargetUserName"; Expression={$_.Properties[5].Value}},
@{Name="TargetDomainName";Expression={$_.Properties[6].Value}},
@{Name="TargetLogonId";Expression={$_.Properties[7].Value}},
@{Name="LogonType";Expression={$_.Properties[8].Value}},
@{Name="LogonProcessName";Expression={$_.Properties[9].Value}},
@{Name="AuthenticationPackageName";Expression={$_.Properties[10].Value}},
@{Name="WorkstationName";Expression={$_.Properties[11].Value}},
@{Name="LogonGuid";Expression={$_.Properties[12].Value}},
@{Name="TransmittedServices";Expression={$_.Properties[13].Value}},
@{Name="LmPackageName";Expression={$_.Properties[14].Value}},
@{Name="KeyLength";Expression={$_.Properties[15].Value}},
@{Name="ProcessId";Expression={$_.Properties[16].Value}},
@{Name="ProcessName";Expression={$_.Properties[17].Value}},
@{Name="IP"; Expression={$_.Properties[18].Value}},
@{Name="IpPort";Expression={$_.Properties[19].Value}}} -throttle 100 |
Export-Csv -path "C:\users\username\Desktop\folder\full.csv"
您可能會考慮設置Runspaces和RunspacePools 。 設置起來有些棘手,但是它們的工作方式非常酷而且非常有效。 池允許您設置各種限制。 RunspaceFactory將作業加載到x個插槽中的1個中,然后一旦完成將其扔入該插槽中的另一個。 這樣做的最大優點之一是開銷-或缺少開銷。 運行空間不需要PowerShell的另一個實例,而Jobs則需要。
因此,如果您要運行一個寬度為50的RunspacePool,並且要處理1000個作業,那么其中50個作業將隨時運行。 超酷。
從mjolinor查看此示例 。 當然,這是一個非常復雜的示例。 他在訪問各種數據流時遇到了很多麻煩。 這樣就可以監視池中的進程。
以下是根據我的主要安全審核事件日志文件(20MB)測得的單項作業速度提高了約50倍。
您的代碼問題是由標准的PowerShell東西引起的,在大量數據的情況下,效率極低。
具有20個計算屬性的Select-Object為每個記錄創建20個ScriptBlock上下文。 與內部的實際簡單代碼相比,在PS中創建上下文需要花費大量時間。
Get-WinEvent為每個事件創建自定義對象,其中包含20多個NoteProperty對象,
每個創建都需要時間。
除了使用慢速PS管道外,Export-CSV還需要訪問每個NoteProperty。
|
流水作業比foreach(不是cmdlet)之類的流控制語句慢。
讓我們開始工作,使用.NET 3.5+和PS3 +手動完成所有工作:
$CollectLogonsInCsv = {
param(
[ValidateScript({ Test-Path -literal $_ })]
[string]$eventLogPath,
[Parameter(Mandatory)]
[string[]]$users,
[ValidateScript({ Test-Path -IsValid -literal $_ })]
[string]$outputPath = ($eventLogPath -replace '[^.]+$', 'csv')
)
$query = '*[System/EventID=4624 and EventData[' +
($users -replace '^.+', 'Data[@Name="TargetUserName"]="$&"' -join ' or ') + ']]'
$reader = [Diagnostics.Eventing.Reader.EventLogReader]::new(
[Diagnostics.Eventing.Reader.EventLogQuery]::new($eventLogPath,
[Diagnostics.Eventing.Reader.PathType]::FilePath, $query)
)
$writer = [IO.StreamWriter]::new($outputPath, $false, [Text.Encoding]::UTF8, 16MB)
$writer.WriteLine('MachineName, RecordId, TimeCreated, Id,' +
'SubjectUserSid, SubjectUserName, SubjectDomainName, SubjectLogonId, ' +
'TargetUserSid, TargetUserName, TargetDomainName, TargetLogonId, ' +
'LogonType, LogonProcessName, AuthenticationPackageName, WorkstationName, ' +
'LogonGuid, TransmittedServices, LmPackageName, KeyLength, ' +
'ProcessId, ProcessName, IP, IpPort')
while ($e = $reader.ReadEvent()) {
$p = $e.properties
$writer.WriteLine('"' +
[string]::Join("`0",
$($e.MachineName, $e.RecordId, $e.TimeCreated, $e.Id; $p[0..19].value)
).replace('"', '""').replace("`0", '","') + '"'
)
}
$writer.close()
[GC]::Collect()
}
現在,使用RunSpaces並行調用它以進行進一步改進:
$outputDir = 'C:\Users\Administrator\Desktop\folder\4768'
Get-Content C:\users\Administrator\Desktop\fullfiles.csv |
Invoke-Parallel -throttle 100 -ImportModules -ImportVariables -ScriptBlock {
$outputCsv = Join-Path $outputDir ((Get-Item -literal $_).BaseName + '.csv')
& $CollectLogonsInCsv $_ @(
'user.name.1'
'user.name.2'
'user.name.3'
'user.name.4'
) $outputCsv
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.