【发布时间】:2015-04-25 09:04:30
【问题描述】:
我有几个 PowerShell 脚本用于管理中型 Microsoft Exchange 组织(约 10,000 个邮箱)。一些脚本以某种方式处理组织的所有邮箱。我在运行这些脚本时遇到的一个常见问题是资源耗尽。这些脚本最终会使用千兆字节的 RAM。
我的研究表明,使用管道可以避免内存消耗,因为在处理之前不会将结果加载到数组中。但是,在某些情况下,Get-Mailbox 似乎仍会将整个结果列表加载到内存中,然后再尝试将这些结果传递给管道中的下一个命令。
例如,我假设以下示例代码将在命令执行后立即开始列出与每个邮箱关联的移动设备:
示例 1
function GetMailboxDevices
{
process
{
Write-Host $_.Alias -ForegroundColor Green
Get-MobileDevice -Mailbox $_
}
}
Get-Mailbox -ResultSize Unlimited | GetMailboxDevices
但是,当 Get-Mailbox cmdlet 运行时,此代码似乎不会实时处理结果。相反,Get-Mailbox 似乎需要几分钟才能运行,然后立即将所有结果传递给管道中的第二个命令。在此过程中,PowerShell 会话的 RAM 使用率攀升至 1.5 GB 或更高。
不过,我可以使用类似于以下的代码来解决此问题:
示例 2
function GetMailboxAliases
{
process
{
Write-Host $_.Alias -ForegroundColor Green
$_.Alias
}
}
$aliases = Get-Mailbox -ResultSize Unlimited | GetMailboxAliases
foreach ($alias in $aliases)
{
Get-MobileDevice -Mailbox $alias
}
在第二个示例中,Get-Mailbox 确实将每个结果实时传递到管道中,而不是一次全部传递(Write-Host 证实了这一点),并且 RAM 使用量没有显着增加。当然,这段代码并不像我必须将别名收集到一个数组中那样优雅,然后使用 foreach 语句处理该数组。
如果我在函数中做一些简单的事情(例如简单地返回每个邮箱的别名),管道似乎很有效,但是一旦我将另一个 Exchange cmdlet 引入函数(例如 Get-MobileDevices )。
我的问题是:为什么示例 1 中的代码不能有效地利用管道,而示例 2 可以?可以采取哪些步骤来确保有效利用管道?
【问题讨论】:
标签: powershell exchange-server pipeline