【问题标题】:Powershell Remoting Speeding up a Foreach Loop Hosted ExchangePowershell 远程处理加速 Foreach 循环托管交换
【发布时间】:2011-06-20 23:12:21
【问题描述】:

我有一个电子邮件地址和部门的 CSV,需要在 Live@edu 上设置。我目前拥有的命令如下所示:

Import-CSV departments.csv | ForEach-Object { Set-User $_.EmailAddress $_.Department }`

问题是,这个操作需要永远。

我的第一个想法是,将ForEach-Object 命令实际转发到远程机器会很棒,这样它只需要在两台机器之间创建一个管道,但是当我进入PSSession,似乎没有任何foreach-object 可用。作为参考,我如何导入 PSSession 是:

Import-PSSession(New-PSSession -ConfigurationName Microsoft.Exchange `
    -ConnectionUri 'https://ps.outlook.com/powershell' `
    -Credential (Get-Credential) `
    -Authentication Basic -AllowRedirection)

有没有更好的方法可以导入会话以允许 ForEach-Object 远程,或者导入远程 foreach-object 的别名版本,可能是 ForEach-Object-Remote,或者可能有人有什么最好建议简化此流程?

更新: 我尝试过的几件事:

  1. 在隐式远程命令上使用-AsJob 开关。

    Import-CSV departments.csv | ForEach-Object { Set-User $_.EmailAddress $_.Department -AsJob }
    

    不幸的是,这不起作用,因为存在不允许额外连接的限制。更糟糕的是,我什至不知道出了什么问题,直到我检查了结果,发现其中很少有人真正改变了。

  2. 以不同的名称导入ForEach-Object

    事实证明,添加前缀很容易,只需将-Prefix RS 放入Import-PSSession 命令中,即可使远程会话中的 ForEach-Object 之类的内容在本地会话中变为ForEach-RSObject。不幸的是,这对我不起作用,因为我要连接的服务器没有我可用的 Microsoft.Powershell ConfigurationName。

更新 2:Set-User cmdlet 似乎是 Microsoft 为 Live@edu 管理提供的。其目的是设置用户属性。它不是我能够调试的脚本或 cmdlet。不幸的是,它不需要管道输入,因此无法解决问题。

据我所知,问题在于,每次运行此命令时,它都必须构造和拆除通往远程机器的管道,而不是能够重用它。远程 ForEach 想法将允许我卸载该循环以避免必须创建所有这些远程管道,而 -asJob 将允许它们全部并行运行。但是,它也导致错误以静默方式失败,并且只有少数记录真正得到正确更新。

我怀疑此时我将无法加快此命令的速度,但必须尽我所能通过更好地跟踪我的内容来限制在特定运行中需要更改的数据量以前做过(保留差异快照)。让工作变得更加困难。

编辑:Start-Automate 留下了非常有用的帮助,不幸的是,它们都不起作用。在这一点上,我的感觉是,在我的提供商允许访问更多的 powershell cmdlet,或者修改交换 cmdlet 以允许多个管道之前,我不会找到一种方法来加快速度,我预计这两种情况都不会很快发生.我将他的答案标记为正确,尽管最终结果没有任何显着帮助。谢谢,开始自动化

【问题讨论】:

  • 如果您能更详细地说明什么是“永远”,那将会有所帮助。 Set-User做什么?如果它不产生任何输出,则很难判断其滞后于何处。我会添加几个Write-Debug 以获得更好的视图。

标签: powershell foreach exchange-server powershell-remoting


【解决方案1】:

您可以加快您的脚本速度,也可以避免尝试通过使用 foreach 语句而不是 Foreach-Object 来建立与服务器的两个连接。

$departments = @(import-csv .\departments.csv)

foreach ($user in $departments) {
    Set-User $user.EmailAddress $user.Department 
} 

如果你需要批处理,你可以使用 for 语句,在每个批处理中前进

for ($i =0; $i -lt $departments.Count; $i+=3) {
     $jobs = @()
     $jobs+= Invoke-Command { Set-User $departments[$i].EmailAddress $departments[$i].Department } -AsJob
     $jobs+= Invoke-Command { Set-User $departments[$i + 1].EmailAddress $departments[$i + 1].Department } -AsJob
     $jobs+= Invoke-Command { Set-User $departments[$i + 2].EmailAddress $departments[$i + 2].Department } -AsJob
     $jobs | Wait-job | Receive-job
}

希望对你有帮助

【讨论】:

  • foreach 和 Forach-Object 的区别在于后者使用的是管道,这反过来会产生性能影响。参考:PosholicBSonPoSH
  • 仍在测试第二个想法,但我不明白使用 foreach 循环而不是 foreach-object 将如何避免或简化与服务器的连接,因为在任何一种情况下,唯一的远程命令都是设置用户命令。
  • 总的来说,有两个很棒的想法,但实际上都不会表现得更好。我可以从 Exchange 获得的 powershell 子集非常有限,并且 Exchange 管理控制台 Powershell Cmdlet 在处理远程管道方面非常有限。第一个 确实 工作,尽管出于我的目的,总体上忽略使用 foreach-object 获得管道的内存管理所需的稍长的时间可能会更好。第二个不能在任何远程 Exchange 服务器上运行,因为 Exchange 命令不允许多个管道。
  • 您可以通过简单地使用 Invoke-Command 并使用 New-PSSession 创建多个连接来绕过并发。据我记得,Exchange 一次限制为 3 个入站连接。
猜你喜欢
  • 2020-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多