【发布时间】:2016-05-23 16:39:50
【问题描述】:
我正在编写一个工作脚本,它将查询我们所有的 AD 域,然后返回具有管理员权限的计算机。下面的脚本可以运行并返回预期的结果,但在我们较大的域中它非常慢。
当处理 23k 或更少的对象时,它只需几分钟(6 分钟左右)即可运行,但当它必须处理 90k+ 时,它会花费数小时。
我是 PowerShell 的新手,不知道这里的哪些操作会使运行时间呈指数增长,所以我无法缩小范围。我的预感是它必须处理 PowerShell 扩展数组以不断添加更多对象的方式?我也在考虑更好地利用管道......但是作为新手并且来自 bash 我不熟悉这个概念以及如何在这段代码中使用它
有什么方法可以加快运行速度,使其运行速度超过几个小时?任何帮助将不胜感激。
$date = Get-Date -uFormat %d-%m-%y
ForEach($domain in $domains)
{
$all_computers = Get-ADComputer -Server $domain -filter * -Properties enabled | select-object name,enabled,@{name="distinguishedname";expression={$_.DistinguishedName -replace "(CN[^,]+,)"}}
#Gets all of the objects that are in a group and pulls their names this is to get the admin flag that is appended to names in this group
$group_name = (Get-ADGroup -Server $domain -Filter{name -like "*admin*"}).Name
#Counts the devices pulled from the computer query
$DevNum = $all_computers.count
echo "Number of devices: " $DevNum > "$domain LARGE $date.txt"
#Remove servers from the list
$all_computers = $all_computers | ?{ $_ -NotMatch "Servers" }
#Counts the number of servers we removed
$NumSkipped = $DevNum - $all_computers.count
Switch($all_computers){
#Finding all of the accounts where both types of admins exist and removing them from the master list
{$group_name -contains $($_.name + "Admins") -and $group_name -contains $($_.name + "UPEPAdmins")} {$_ | Add-Member "admintype" "both";Continue}
#Finding all of the accounts with only exception admins and removing them from the master list
{$group_name -contains $($_.name + "Admins")} {$_ | Add-Member "admintype" "old";Continue}
#Finding all of the accounts with only upep admins and removing them from the master list
{$group_name -contains $($_.name + "UPEPAdmins")} {$_ | Add-Member "admintype" "UPEP";Continue}
#These accounts have no admin
default {$_ | Add-Member "admintype" "No"}
}
echo "Number of servers skipped: " $NumSkipped >> "$domain LARGE $date.txt"
echo "Number of workstations: " $all_computers.count >> "$domain LARGE $date.txt"
echo "Number of Exception admins found: " $($all_computers|?{$_.admintype -match "old|both"}).count >> "$domain LARGE $date.txt"
echo "Number of UPEP admins found: " $($all_computers|?{$_.admintype -match "upep|both"}).count >> "$domain LARGE $date.txt"
echo "Number of both UPEP and Exception admins found: " $($all_computers|?{$_.admintype -eq "both"}).count >> "$domain LARGE $date.txt"
#output
$all_computers | Export-Csv "$domain LARGE $date.csv"
}
编辑 1:
更新了代码以反映 SodaWillow、TheMadTechnician 和 删除修剪并用 -replace 替换它会减少一点运行时间。
编辑 2:
将代码更新为正确的解决方案,根据 TheMadTechnician 的建议,我过滤了组以减少其数量,并将组名插入到数组而不是表中。与减少的组数结合使用时,数组的使用显着加快了操作速度。
当前错误:“Both”管理类型正确导出为 CSV,但根本没有在文本文件中报告,我认为这与 if 语句中的逻辑有关。我现在正在看这个
编辑 3:
修复了两个管理类型的逻辑错误,这是这个问题的最终解决方案。 由于私有信息,$domains 变量被声明在此代码块之外。
感谢大家的宝贵时间!
【问题讨论】:
-
您可能想尝试 LDAP 过滤器和
System.DirectoryServices.DirectorySearcher(此处的示例:powershelladmin.com/wiki/…)。测量代码的每个部分所消耗的时间以找到最长的查询,然后从优化这些查询开始(如果您还没有这样做的话) -
我尝试在代码块上运行并使用 Measure-Command 来查看我可能在哪里增加了不必要的时间。似乎没有什么是多余的,但放在一起需要很长时间
-
我会想象 L2 和 L4 的持续时间比其他的要长得多。 L4 可以用
Get-ADGroup重写吗? -
是的,那些需要热度。几分钟一片。但没有什么不合理的。看起来修剪(L28 和 L37)是重击者,会用那个子表达式代替修剪的工作吗?我不只是使用 get-adgroup 的原因是,由于 AD 组织不善,我需要的指标信息在 adcomputer 和 ad group 之间分配。
-
之后有很多处理,需要完全分解和理解以优化脚本。我会尝试潜入:)。
标签: powershell active-directory