Предполагается, что этот сценарий захватывает пользователей из нескольких подразделений и назначает пользователей одной переменной, затем он берет пользователей из этой переменной и фильтрует каждого из них на основе дат последнего входа в систему старше 30 дней. Затем он экспортирует в CSV некоторую информацию, которую я хотел бы.
Проблема в, когда я доберусь до для каждого часть, он просматривает весь каталог и не использует пользователей в указанной мной переменной.
Любая критика также приветствуется.
$30days = (get-date).adddays(-30)
$Users1 = Get-ADUser -SearchBase 'OU=Users,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com' -LdapFilter '(UserPrincipalName=*)(extensionAttribute9=*)'
$Users2 = Get-ADUser -SearchBase 'OU=Users-Remote,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com' -LdapFilter '(UserPrincipalName=*)(extensionAttribute9=*)'
$Users3 = Get-ADUser -SearchBase 'OU=Contractors,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com' -LdapFilter '(UserPrincipalName=*)(extensionAttribute9=*)'
$Users4 = Get-ADUser -SearchBase 'OU=Temps,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com' -LdapFilter '(UserPrincipalName=*)(extensionAttribute9=*)'
$Users5 = Get-ADUser -SearchBase 'OU=Users,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com' -LdapFilter '(UserPrincipalName=*)(extensionAttribute9=*)'
$Users6 = Get-ADUser -SearchBase 'OU=Users,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com' -LdapFilter '(UserPrincipalName=*)(extensionAttribute9=*)'
$Users = $Users1,$Users2,$Users3,$Users4,$Users5,$Users6
$useraccountsover30days = foreach ($user in $($Users)){Get-ADUser -filter {lastlogondate -le $30days} -Properties lastlogondate}
$lastlogonreadable = $useraccountsover30days | Select-Object SamAccountName,lastlogondate
$lastlogonreadable | Export-Csv C:/Users/myname/Desktop/Usersover30days.csv
Я бы дал несколько рекомендаций по вашему текущему сценарию.
Во-первых, один большой запрос почти всегда будет работать лучше, чем множество более мелких запросов. Так что вместо того, чтобы бегать get-aduser
отдельно для каждого целевого OU, я бы объединил их в один вызов, используя общий OU более высокого уровня в качестве базы поиска. Очевидно, это может привести к возврату результатов из организационных единиц, которые вы не хотели включать. Но позже их гораздо быстрее отфильтровать.
Ты тоже звонишь get-aduser
снова для каждого результата из первого набора запросов просто для фильтрации по lastLogonDate. Но вместо этого вы можете объединить этот фильтр с -ldapfilter
из ваших исходных запросов. Это просто вопрос преобразования -filter
версия с эквивалентом -ldapfilter
версия. Секрет в том, чтобы знать, что lastLogonDate - это просто преобразованная в Powershell версия атрибута lastLogonTimestamp. И вы можете преобразовать обычное значение DateTime Powershell в формат, который lastLogonTimestamp использует с ToFileTime()
метод.
Последнее, что меня смутило, было (UserPrincipalName=*)
часть вашего ldapfilter. В каждом домене, которого я когда-либо касался, этот атрибут всегда будет иметь значение (как SamAccountName или DistinguishedName). Оно может отличаться от значения по умолчанию <SamAccoutnName>@<DomainFQDN>
, но он никогда не бывает пустым. Фильтр не обязательно ничего вредит. Для AD это всего лишь одна дополнительная вещь, позволяющая тратить циклы ЦП на оценку, когда в этом нет необходимости. Но если у вас есть основания полагать, что он может быть пустым в вашем окружении, во что бы то ни стало оставьте его.
Итак, вот как я бы изменил ваш сценарий, если я правильно понимаю ваши намерения.
# make the comparison value using ToFileTime()
$30daysago = (Get-Date).AddDays(-30).ToFileTime()
# make the combined ldapfilter value
$LdapFilter = "(&(lastLogonTimestamp<=$30daysago)(extensionAttribute9=*)"
# make an array of the OU DNs you care about
$TargetOUs = @(
"OU=Users,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com"
"OU=Users-Remote,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com"
"OU=Contractors,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com"
"OU=Temps,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com"
)
# define your common search base
$base = "OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com"
# get your combined results and the additional attributes you care about
$OldUsers = get-aduser -ldapfilter $LdapFilter -searchbase $base -pr lastLogonDate
# convert the target OU list into a regular expression we can compare each DN against in a single comparison call
$regex = ""
$TargetOUs | %{ $regex += ".*," + [Regex]::Escape($_) + "$|" }
$regex = $regex.Substring(0,$regex.Length-1)
# filter the results that aren't in your target OUs
# (depending on your OU layout, it might be more efficient to flip this
# and define the OUs you explicitly want to leave out)
$FilteredUsers = $OldUsers | ?{ $_.DistinguishedName -match $regex }
# export your CSV (sorted for good measure)
$FilteredUsers | select SamAccountName,LastLogonDate | sort LastLogonDate | export-csv C:/Users/myname/Desktop/Usersover30days.csv
P.S. Остерегайтесь лечения lastLogonTimestamp
(или lastLogonDate
) со 100% точностью. Это может быть где угодно Срок хранения от 9 до 14 дней по дизайну.
Я решил аналогичный запрос для нескольких OU с повторением одного и того же набора, как показано ниже, несколько раз с указанным OU:
get-aduser -filter 'enabled -eq $true' -Properties Name, LastLogonDate, AccountExpirationDate, description, Department, title, UserPrincipalName -SearchBase "OU=Users,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com" | Where-object {$_.lastlogondate -lt (get-date).AddDays(-30)} | Select-Object Name, LastLogonDate, AccountExpirationDate, description, Department, title, UserPrincipalName | Export-csv C:\temp\users-nologin-30.csv -Encoding UTF8 -Append -NoTypeInformation -Force -Delimiter ";"
Он получает все включенные учетные записи со свойствами Name, LastLogonDate, AccountExpirationDate, description, Department, title, UserPrincipalName и добавляет их в csv-файл. Как указано в другом ответе, 30 дней может быть неточным, поэтому лучше позвонить в течение 44 дней, чтобы быть уверенным.
Если «LastLogonDate» пусто, пользователь никогда не входил в систему, возможно, это новая учетная запись.
Вы никогда не используете значение $ user в вызове Get-ADUser ... попробуйте изменить значение $ UsersX на параметры, которые необходимо отправить в Get-ADUser, и замените их ... и, поскольку вы повторно используете тот же LdapFilter, может также сделать это переменной. (Кроме того, вы трижды повторно используете "OU = Users, OU = US-Location", я полагаю, это просто для примера?)
$30days = (get-date).adddays(-30)
$LdapFilter = '(UserPrincipalName=*)(extensionAttribute9=*)'
$Users1 = 'OU=Users,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com'
$Users2 = 'OU=Users-Remote,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com'
$Users3 = 'OU=Contractors,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com'
$Users4 = 'OU=Temps,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com'
$Users5 = 'OU=Users,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com'
$Users6 = 'OU=Users,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com'
$Users = $Users1,$Users2,$Users3,$Users4,$Users5,$Users6
$useraccountsover30days = foreach ($user in $($Users)){Get-ADUser -SearchBase $user -LdapFilter $LdapFilter -filter {lastlogondate -le $30days} -Properties lastlogondate}
$lastlogonreadable = $useraccountsover30days | Select-Object SamAccountName,lastlogondate
$lastlogonreadable | Export-Csv C:/Users/myname/Desktop/Usersover30days.csv