繁体   English   中英

如何加快AD对象上的PowerShell操作

[英]How to speed up PowerShell operations on AD objects

我正在编写一个工作脚本,它将查询我们所有的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的建议的基础上我过滤了组以减少它们的数量,并且还将组名插入到数组而不是表中。 当与减少的组数相结合时,阵列的使用显着加速了操作。

当前错误:“两个”管理员类型正在正确导出到CSV但根本没有在文本文件中报告,我认为它与if语句中的逻辑有关。 我正在看那个

编辑3:

修复了两种管理类型逻辑错误,这是此问题的最终解决方案。 由于私有信息,$ domains var在此代码块的视图之外被声明。

谢谢大家的时间!

好吧,看起来至少你可以从组合一些线路中受益。 您可以在一些地方定义变量,然后通过过滤自身立即重新定义变量。 如:

$servs = $all_computers | Select-Object Name,DistinguishedName
$servs = $servs -Match "Servers" 

可以简化为:

$servs = $all_computers | Select-Object Name,DistinguishedName | Where {$_ -match "Servers"}

现在为$admin_exist_cnt$upep_admin_exist_cnt做同样的事情

$admin_exist_cnt = Compare-Object -DifferenceObject $group_name -ReferenceObject $com_name_admin -ExcludeDifferent -IncludeEqual -Property name | select-object @{name="name";expression={$($_.name).toString().TrimEnd("A","d","m","i","n","s")}}

$upep_admin_exist_cnt = Compare-Object -DifferenceObject $group_name -ReferenceObject $com_name_upep -ExcludeDifferent -IncludeEqual -Property name | Select-Object @{name="name";expression={$($_.Name).ToString().TrimEnd("U","P","E","P","A","d","m","i","n","s")}}

然后在接近结束时,您将浏览所有寻找“两个”管理类型的计算机,并从$all_computers变量中删除它们,然后再次运行整个过程,并执行4次。 不,不要这样做,请改用Switch命令。 它看起来像这样:

Switch($all_computers){
    #Finding all of the accounts where both types of admins exist and removing them from the master list
    {$both_exist_cnt.name -contains $_.name} {$_ | Add-Member "admintype"  "both";Continue}
    #Finding all of the accounts with only exception admins and removing them from the master list
    {$admin_exist_cnt.name -contains $_.name} {$_ | Add-Member "admintype" "old";Continue}
    #Finding all of the accounts with only upep admins and removing them from the master list
    {$upep_admin_exist_cnt.name -contains $_.name} {$_ | Add-Member "admintype" "UPEP";Continue}
    #These accounts have no admin
    default {$_ | Add-Member "admintype" "No"}
}

然后你可以将输出部分减少到:

#output
$all_computers | Export-Csv test.csv

编辑:好的,回过头来看看你重新定义了很多东西。 相反,我建议只通过一次Switch运行它,然后计算你的结果。 这将大大减少内存消耗,这在小型测试运行中可能无关紧要,但在大量运行时应该会产生相当大的差异。 试试这个修改过的脚本,如果您有任何具体问题请告诉我:

#TODO Fix the server thing and put it in a for loop
$all_computers = Get-ADComputer -Server NW -filter * -Properties enabled | select name,enabled,distinguishedname
#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-ADObject -Server NW -Filter{objectCategory -eq "group"} | select name

#Counts the devices pulled from the computer query
#TODO Replace "test.txt" with a descriptive file name
$DevNum = $all_computers.count
echo "Number of devices: " $DevNum > test.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.name -contains $($_.name + "Admins") -and $group_name.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.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.name -contains $($_.name + "UPEPAdmins")} {$_ | Add-Member "admintype" "UPEP";Continue}
    #These accounts have no admin
    default {$_ | Add-Member "admintype" "No"}
}

#TODO Replace "test.txt" with a descriptive file name
echo "Number of servers skipped: " $NumSkipped >> test.txt

#Calculating the number of workstations 
echo "Number of workstations: " $all_computers.count >> test.txt

#TODO Replace "test.txt" with a descriptive file name
echo "Number of Exception admins found: " $($all_computers|?{$_.admintype -match "old|both"}).count >> test.txt

#TODO Replace "test.txt" with a descriptive file name
echo "Number of UPEP admins found: " $($all_computers|?{$_.admintype -match "upep|both"}).count >> test.txt

#Find both exception and upep admin names
if($($all_computers|?{$_.admintype -ne "No"}))
{
        echo "Number of both UPEP and Exception Admins: 0" >> test.txt
}else
{
        echo "Number of both UPEP and Exception Admins: " $($all_computers|?{$_.admintype -match "both"}).count >> test.txt
}

#output
$all_computers | Export-Csv test.csv

根据您可用的powershell版本(您需要PSv4),您可以在列表中使用.where方法,速度要快得多:

$servs = $all_computers.where{$_ -match "Servers"} | Select-Object Name,DistinguishedName

我怀疑使用select后来也快一点,但这只是猜测。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM