提高invokeparallel scriptb的效率和速度

2024-04-24 16:00:34 发布

您现在位置:Python中文网/ 问答频道 /正文

有没有一种方法可以加速这个命令并使它更有效地使用资源?在

如果文件不需要提取并且可以通过evtx文件格式解析,我愿意转换为python3.5。在

我有一个使用cmdlet invoke parallel与脚本块一起运行的脚本。$files是我根据用户名和事件ID筛选的10000个evtx文件的列表。在

我试图调用的新实例powershell.exe并从scriptblock运行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"   

Tags: 文件实例方法name命令脚本valuefiles
2条回答

您可以考虑设置Runspaces and RunspacePools。它们的设置有点棘手,但它们的工作方式非常酷而且非常高效。游泳池可以让你设置各种各样的节流阀。RunspaceFactory将一个作业加载到x个槽中的1个,然后一旦其中一个槽完成,它就会将另一个作业扔到该槽中。 这样做的一大优点是开销,或者说没有开销。运行空间不需要另一个PowerShell实例,而Jobs需要。在

因此,如果您有一个宽度为50和1000个作业的RunspacePool,其中50个作业将在任何时候运行。超级酷。在

Check out this example from mjolinor。 当然,这是一个相当复杂的例子。他费了不少周折才获得对各种数据流的访问权。这使得监视池中的进程成为可能。在

下面是在我的主安全审计事件日志文件(20MB)上测量的单个作业的大约50倍的速度。在

代码中的问题是由标准的PowerShell内容引起的,在处理大量数据时效率非常低下。在

  • 具有20个计算属性的Select Object为每个记录创建20个ScriptBlock上下文。与内部实际的简单代码相比,PS中的上下文创建需要花费大量时间。

  • Get WinEvent为每个事件创建自定义对象,其中包含20多个NoteProperty对象,
    每一个都需要时间去创造。

  • Export CSV除了使用慢速PS管道外,还需要访问每个NoteProperty

  • |管道比流控制语句(如foreach(not cmdlet))慢,while。

让我们开始使用.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()
}

现在使用运行空间并行地调用它以进一步改进:

^{pr2}$

相关问题 更多 >