如何优化跨所有域控制器的查询以找到最新的登录日期?
How to optimize query across all domain controllers to find the latest logon date?
我目前正在尝试查询域控制器以查找用户的最新登录日期。我知道我可以使用 lastlogondate,但它不会像我想要的那样经常被复制,而且我无法控制它。我尝试制作一个脚本来查询每个域控制器并根据用户哈希表对其进行检查,但事实证明即使查询一个 DC 也非常慢。我知道我可以 运行 每个 DC 的后台作业,但仍然只是为一个域控制器执行所有最新登录时间需要很长时间。有什么建议吗?
$dcs = Get-ADDomainController -Filter {Name -like "*"}
$users = Get-ADUser -filter * -SearchBase "OU=users,DC=com"
$outfile = "c:users.csv"
$usertable = @{}
# creating table for all users
foreach($user in $users) {
$userobject = New-Object PSObject
$userobject | Add-Member -MemberType NoteProperty -Name DomainController -Value "0"
$userobject | Add-Member -MemberType NoteProperty -Name LastLogon -Value "0"
$usertable.Add($user.SamAccountName ,$userObject)
} # end foreach
# Method for looping through domain controllers to find last logon
foreach($dc in $dcs) {
$hostname = $dc.HostName
$logons = Get-ADUser -Filter * -SearchBase "OU=users,DC=com" -Property LastLogon -Server $hostname
foreach($u in $logons) {
$sam = $u.SamAccountName
if($u.LastLogon -gt $usertable.$sam.LastLogon) {
$usertable.$sam.LastLogon = $u.LastLogon
$usertable.$sam.DomainController = $dc.HostName
Write-Host "$sam has the latest date"
$usertable.$sam.DomainController
}
} #end inner foreach
} #end outer domain foreach
foreach($h in $usertable.GetEnumerator()) {
$sam = $($h.Name)
$newdate = $($h.Value).LastLogon
$append = "$sam,$newdate"
$append | out-file $outfile -Encoding ascii -Force -Append
}
我想我已经明白了。测试和我自己的类似程序对比很明显,延迟在下面的循环中:
foreach($u in $logons) {
$sam = $u.SamAccountName
if($u.LastLogon -gt $usertable.$sam.LastLogon) {
$usertable.$sam.LastLogon = $u.LastLogon
$usertable.$sam.DomainController = $dc.HostName
Write-Host "$sam has the latest date"
$usertable.$sam.DomainController
}
} # end inner foreach
现在我的程序和你的不完全一样。人们可以对此进行清理,但出于所有意图和目的,以下部分与上述摘录具有相同的功能:
# Note: the re-use of $DC...
ForEach($DC in $RDCs )
{ # Should you add any measurements here??
Write-Host "Working on $DC : $(Get-Date -Format G) ..."
Get-ADUser -Filter $Filter -SearchBase $SearchBase -Server $DC -Properties $AD_Props |
ForEach-Object{
If ( $Users.Contains( $_.samAccountName ) )
{ # So you don't attemp when it wasn't in the root set.
If( $_.lastlogon -gt $Users[$_.samAccountName].LastLogon )
{
$Users[$_.samAccountName].LastLogon = $_.lastlogon
$Users[$_.samAccountName].DC = $DC
}
}
}
}
您可以看到我使用的是 ForEach-Object
循环而不是 ForEach
结构。然而,这并不是一个充分的解释,尤其是考虑到后者通常更快。
注意:我以几种不同的方式为您的循环计时,并在脚本的前面说明了代码。例如,我没有以相同的方式创建对象,但我排除了这个因素。
无法弄清楚为什么你的循环会“显着”变慢我不情愿地将它重写为:
$logons |
ForEach-Object{
If( $_.LastLogon -gt $usertable[$_.samAccountName].LastLogon )
{
$usertable[$_.samAccountName].LastLogon = $_.LastLogon
$usertable[$_.samAccountName].DomainController = $hostname
但是,这似乎并没有快多少。所以,我更不情愿地试了一下:
Get-ADUser -Filter * -SearchBase $UsersOU -Property LastLogon -Server $hostname |
ForEach-Object{
If( $_.LastLogon -gt $usertable[$_.samAccountName].LastLogon )
{
$usertable[$_.samAccountName].LastLogon = $_.LastLogon
$usertable[$_.samAccountName].DomainController = $hostname
}
}
现在我开始看到与我自己的程序相似的性能。其实好像快了一点,可能是没有检查Hash的缘故。
根据经验,我只能假设这些对象是活动的,并保持某种与源 DC 的连接。我以前在 PowerShell 社区扩展 (PSCX) 中见过这种类型的东西,从 Get-TerminalSession
返回的对象表现出类似的行为。我可能是疯了,我很高兴得到纠正,坦率地说希望有人有更好的解释。
我可以在这里提出一些其他建议,none 与上述一样有影响力。另请注意,我没有测试到最后,所以不能保证没有其他问题。
我目前正在尝试查询域控制器以查找用户的最新登录日期。我知道我可以使用 lastlogondate,但它不会像我想要的那样经常被复制,而且我无法控制它。我尝试制作一个脚本来查询每个域控制器并根据用户哈希表对其进行检查,但事实证明即使查询一个 DC 也非常慢。我知道我可以 运行 每个 DC 的后台作业,但仍然只是为一个域控制器执行所有最新登录时间需要很长时间。有什么建议吗?
$dcs = Get-ADDomainController -Filter {Name -like "*"}
$users = Get-ADUser -filter * -SearchBase "OU=users,DC=com"
$outfile = "c:users.csv"
$usertable = @{}
# creating table for all users
foreach($user in $users) {
$userobject = New-Object PSObject
$userobject | Add-Member -MemberType NoteProperty -Name DomainController -Value "0"
$userobject | Add-Member -MemberType NoteProperty -Name LastLogon -Value "0"
$usertable.Add($user.SamAccountName ,$userObject)
} # end foreach
# Method for looping through domain controllers to find last logon
foreach($dc in $dcs) {
$hostname = $dc.HostName
$logons = Get-ADUser -Filter * -SearchBase "OU=users,DC=com" -Property LastLogon -Server $hostname
foreach($u in $logons) {
$sam = $u.SamAccountName
if($u.LastLogon -gt $usertable.$sam.LastLogon) {
$usertable.$sam.LastLogon = $u.LastLogon
$usertable.$sam.DomainController = $dc.HostName
Write-Host "$sam has the latest date"
$usertable.$sam.DomainController
}
} #end inner foreach
} #end outer domain foreach
foreach($h in $usertable.GetEnumerator()) {
$sam = $($h.Name)
$newdate = $($h.Value).LastLogon
$append = "$sam,$newdate"
$append | out-file $outfile -Encoding ascii -Force -Append
}
我想我已经明白了。测试和我自己的类似程序对比很明显,延迟在下面的循环中:
foreach($u in $logons) {
$sam = $u.SamAccountName
if($u.LastLogon -gt $usertable.$sam.LastLogon) {
$usertable.$sam.LastLogon = $u.LastLogon
$usertable.$sam.DomainController = $dc.HostName
Write-Host "$sam has the latest date"
$usertable.$sam.DomainController
}
} # end inner foreach
现在我的程序和你的不完全一样。人们可以对此进行清理,但出于所有意图和目的,以下部分与上述摘录具有相同的功能:
# Note: the re-use of $DC...
ForEach($DC in $RDCs )
{ # Should you add any measurements here??
Write-Host "Working on $DC : $(Get-Date -Format G) ..."
Get-ADUser -Filter $Filter -SearchBase $SearchBase -Server $DC -Properties $AD_Props |
ForEach-Object{
If ( $Users.Contains( $_.samAccountName ) )
{ # So you don't attemp when it wasn't in the root set.
If( $_.lastlogon -gt $Users[$_.samAccountName].LastLogon )
{
$Users[$_.samAccountName].LastLogon = $_.lastlogon
$Users[$_.samAccountName].DC = $DC
}
}
}
}
您可以看到我使用的是 ForEach-Object
循环而不是 ForEach
结构。然而,这并不是一个充分的解释,尤其是考虑到后者通常更快。
注意:我以几种不同的方式为您的循环计时,并在脚本的前面说明了代码。例如,我没有以相同的方式创建对象,但我排除了这个因素。
无法弄清楚为什么你的循环会“显着”变慢我不情愿地将它重写为:
$logons |
ForEach-Object{
If( $_.LastLogon -gt $usertable[$_.samAccountName].LastLogon )
{
$usertable[$_.samAccountName].LastLogon = $_.LastLogon
$usertable[$_.samAccountName].DomainController = $hostname
但是,这似乎并没有快多少。所以,我更不情愿地试了一下:
Get-ADUser -Filter * -SearchBase $UsersOU -Property LastLogon -Server $hostname |
ForEach-Object{
If( $_.LastLogon -gt $usertable[$_.samAccountName].LastLogon )
{
$usertable[$_.samAccountName].LastLogon = $_.LastLogon
$usertable[$_.samAccountName].DomainController = $hostname
}
}
现在我开始看到与我自己的程序相似的性能。其实好像快了一点,可能是没有检查Hash的缘故。
根据经验,我只能假设这些对象是活动的,并保持某种与源 DC 的连接。我以前在 PowerShell 社区扩展 (PSCX) 中见过这种类型的东西,从 Get-TerminalSession
返回的对象表现出类似的行为。我可能是疯了,我很高兴得到纠正,坦率地说希望有人有更好的解释。
我可以在这里提出一些其他建议,none 与上述一样有影响力。另请注意,我没有测试到最后,所以不能保证没有其他问题。