Parallelt hentning af bruger sessioner fra flere Windows-servere i PowerShell

Indlæg af Hanne Mølgaard Plasc

Problem



Antag, at jeg har en række Windows-værtsnavne:


$server\_hostnames = @("server1","server2")


For hver server skal jeg finde ud af, om der er nogen sessioner for en bestemt bruger, og derefter ideelt indfange alle sessionerne i et nyt array.


$results = @()
$account = "JohnDoe"
foreach ($s in $server\_hostnames) {
    $r = (qwinsta /server:$($s) 2> $null | out-string -stream | sls $account)
    $results += $r
}


I dette eksempel har jeg 2 servere, men i produktion ville jeg køre den mod 2-3000 servere, så parallel udførelse er ekstremt vigtig.


Jeg har lavet flere forsøg på at omskrive koden ved hjælp af job, arbejdsgang eller Split-Pipeline, men med ringe succes.
Filtrering med sls (Select-String) virker normalt ikke, selv ikke med findstr.


Split-Pipeline eksempel:


PS C:SplitPipeline> $server\_hostnames | Split-Pipeline {process{ $\_; qwinsta /server:$($\_) | out-string -stream | sls $account }}
Split-Pipeline : Cannot bind argument to parameter 'Pattern' because it is null.
At line:1 char:21
+ $server\_hostnames | Split-Pipeline {process{ $\_; qwinsta /server:$($\_) | out-str ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Split-Pipeline], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,SplitPipeline.SplitPipelineCommand

Bedste reference


Brug af job kan du gøre noget som dette:


$servers = 'server1', 'server2'
$account = 'JohnDoe'
$results = @()

$sb = {
  Param($server, $name)
  & qwinsta /server:$server |
    Select-String $name -SimpleMatch |
    Select-Object -Expand Line
}

$servers | ForEach-Object {
  Start-Job -ScriptBlock $sb -ArgumentList $\_, $account | Out-Null
}

$results += while (Get-Job -State Running) {
  Get-Job -State Complete | ForEach-Object {
    Receive-Job -Job $\_
    Remove-Job -Job $\_
  }
}

$results += Get-Job -State Complete | ForEach-Object {
  Receive-Job -Job $\_
  Remove-Job -Job $\_
}


Men da du vil køre qwinsta mod flere tusinde servere, vil du sandsynligvis gerne bruge en jobkø i stedet for at køre alle job på samme tid, ellers kan det enorme antal job udtømme din lokale computers ressourcer .