Параллельное извлечение пользовательских сеансов с нескольких серверов Windows в PowerShell

Предположим, у меня есть массив имен узлов Windows:

$server_hostnames = @("server1","server2")

Для каждого сервера я должен найти, есть ли какие-либо сеансы для конкретного пользователя, а затем в идеале захватить все сеансы в новом массиве.

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

В этом примере у меня есть 2 сервера, но в производстве я бы запустил его против 2-3000 серверов, поэтому параллельное выполнение чрезвычайно важно.

Я сделал несколько попыток переписать код с помощью заданий, рабочих процессов илиSplit-Pipeline, но без особого успеха.
Обычно фильтрация с slsпомощью (Select-String) не работает, даже с findstrпомощью .

Split-Pipeline образец:

PS C:SplitPipeline> $server_hostnames / Split-Pipeline {process{ $_; qwinsta / server:$ ($_) / out-string-stream / sls $account }}
Split-Pipeline: не удается привязать аргумент к параметру 'Pattern', поскольку он равен null.
At line:1 char: 21
+ $server_hostnames / Split-Pipeline {process{ $_; qwinsta / server:$ ($_) / out-str ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 + CategoryInfo : InvalidData: (:) [Split-Pipeline], ParameterBindingValidationException
 + FullyQualifiedErrorId: ParameterArgumentValidationErrornullnotallowed,SplitPipeline.SplitPipelineCommand

1 ответ

  1. Используя задания, вы можете сделать что-то вроде этого:

    $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 $_
    }
    

    Однако, поскольку вы хотите работать qwinstaс несколькими тысячами серверов, вы, вероятно, захотите использовать очередь заданий, а не запускать все задания одновременно, иначе огромное количество заданий может истощить ресурсы вашего локального компьютера.