在PowerShell中从多个Windows服务器并行检索用户会话

时间:2017-01-17 11:18:04

标签: 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重写代码,但收效甚微。 通常情况下,使用slsSelect-String)进行过滤不起作用,即使使用findstr也不行。

Split-Pipeline示例:

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

1 个答案:

答案 0 :(得分:0)

使用工作可以做到这样的事情:

$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,您可能希望使用job queue而不是同时运行所有作业,否则大量的作业可能会耗尽您当地计算机的资源。