Как эффективно использовать параметр `-Filter` в командлетах Active Directory?
Слишком часто я вижу следующий тип кода на этом сайте, специфичный для командлетов AD:
Get-ADUser -Filter * | Where-Object { $_.EmailAddress -eq $email }
Проблема в том, что вы возвращаете каждый отдельный пользовательский объект в Active Directory, а затем обрабатываете его во второй раз. Как мы можем улучшить это, не только чтобы сократить время, необходимое для запуска сценария, но также и снять ненужную нагрузку с Active Directory и, возможно, сети?
1 ответ
Что в этом плохого -Filter *
?
Вы фактически выбираете и возвращаете каждый объект, который существует в AD, в зависимости от используемого командлета (например, Get-ADUser
, Get-ADComputer
, Get-ADGroup
родовой Get-ADObject
и т. д.) - это дорогая вещь, особенно в больших средах AD. Это нормально, если вам по закону нужно работать с каждым возможным объектом, но в большинстве случаев вам не нужно возвращать все. Кроме того, ваш сценарий будет обрабатывать гораздо больше данных, чем нужно, увеличивая время выполнения и время обработки, когда это просто не нужно.
-Filter
Параметр может сделать больше, чем просто сопоставить все, что эффективно -Filter *
делает. Filter
Строка очень похожа на синтаксис Powershell (не совсем, но в большинстве случаев). Вы можете использовать большинство тех же логических операторов, которые поддерживает Powershell, и они работают так же, как и операторы Powershell. Этот ответ призван прояснить это и объяснить, как использовать этот неуловимый параметр. Эти примеры будут использовать Get-ADUser
командлеты, но это также распространяется на другие Get-ADObject
командлеты, которые также используют фильтры.
Синтаксис
Синтаксис для Filter
строка выглядит следующим образом: "PropertyName -comparisonoperator 'somevalue'"
хотя вы можете связать несколько условий вместе с логическими операторами, такими как -and
а также -or
, Обратите внимание, что операторы сопоставления регулярных выражений, такие как -match
а также -notmatch
не работают, но -like
а также -notlike
работать так, как вы ожидаете.
Соответствие на имущество
Чтобы использовать пример в вопросе, давайте найдем пользователя, который соответствует адресу электронной почты, но без указания Where-Object
(безумно верно???):
$email = 'box@domain.tld'
Get-ADUser -Filter "EmailAddress -eq '${email}'"
Готово. Get-ADUser
вернет все учетные записи, в которых свойство EmailAddress равно значению $email
переменная есть.
Что если мы хотим найти все учетные записи пользователей, которые не были зарегистрированы в течение последних 30 дней? Но строка даты является более сложной, чем электронная почта! Кому интересно, все таки довольно просто!
# Get the date from 30 days ago
$notUsedSince = ( Get-Date ).AddDays( -30 )
Get-ADUser -Filter "LastLogonDate -lt '${notUsedSince}'"
Это возвращает всех пользователей, которые не вошли в систему в течение последних 30 дней.
Совпадение по нескольким свойствам
Совпадение по нескольким свойствам не сильно отличается, но лучше заключить каждое условие в скобки ()
, Вот пример, давайте найдем учетные записи администратора домена (если мы знаем это по номенклатуре имени пользователя) *-da
), которые не имеют адрес электронной почты, связанный с ними.
Get-ADUser -Filter "(samaccountname -notlike '*-da') -and (EmailAddress -notlike '*')"
Это немного сложнее, потому что мы не можем передать пустое значение для правой части условия в -Filter
как в случае для EmailAddress
, Но '*' соответствует любому непустому значению, поэтому мы можем использовать это поведение с -notlike
оператор сравнения, чтобы найти пустые значения для EmailAddress
, Чтобы сломать фильтр, убедитесь, что все учетные записи, оканчивающиеся на -da
не сопоставляются фильтром, а также сопоставляются только те учетные записи, которые не имеют EmailAddress
значение.
Вещи, чтобы избежать
Не пытайтесь использовать
{ ScriptBlock }
для ваших параметров фильтра. Да, нам все удобнее писатьScriptBlock
чем беспокоиться о созданииstring
и убедившись, что он избежал правильно. Их использование определенно привлекает. Я видел так много ответов, используяScriptBlock
как-Filter
аргумент, или люди, имеющие проблемы (включая меня), пытающиеся сделать что-то подобное, и СЮРПРИЗ!!! Ничто не возвращаетсяImport-Csv C:\userInfoWithEmails.csv | Foreach-Object { Get-ADUser -Filter { EmailAddress -eq $_.Email } }
-Filter
не поддерживаетScriptBlocks
, но они вид работы иногда ™, потому что они получают ToString'd до оценки. Технически они будут работать, если вы используете простое расширение переменной, например$_
или же$emailAddress
, но это в конечном итоге вызовет у вас головную боль, особенно если вы попытаетесь получить доступ к свойству объекта (как выше), потому что оно просто не будет работать. Каждый раз используйте строковый фильтр, а если вам нужно использовать свойство объекта в качестве параметра фильтра, используйте подстановку переменных или подстановку команд.Вам не нужно указывать дополнительные
-Properties
если вы заботитесь только о свойстве для фильтрации по нему. Командлеты AD могут оценивать все свойства в пределахFilter
параметр без необходимости передавать их по конвейеру.И пока я на это, никогда не использую
-Properties *
Исключая, может быть, если по какой-то причине вы проверяете все свойства возвращаемого объекта. Укажите свойства, которые нужно обработать, только после того, как объект AD был возвращен. Для этого есть причина - некоторые свойства особенно дороги для получения значений. Лучшая практика - перенаправлять только те свойства, которые вам нужны для обработки по конвейеру. Немного не связанный с этим вопросом, но все же очень важная деталь, о которой нужно помнить.
В итоге
Эти методы с использованием -Filter
Параметр с помощью командлетов AD сэкономит вам дорогостоящее время обработки при переборе в больших средах AD и повысит производительность ваших операций Powershell AD. Я надеюсь, что это поможет объяснить некоторые из неуловимых поведений командлетов AD -Filter
параметр.