Предубеждение — вот что долго мешало Windows PowerShell получить признание среди администраторов. Существует предубеждение, что эта оболочка является «языком сценариев» сродни VBScript. Хотя большинство администраторов обожают быстро и эффективно решать задачи с помощью сценариев, но многих пугает их сложность и существенное время, которое надо потратить на их освоение.
Очень, очень жаль. Действительно, оболочка поддерживает подход, основанный на сценариях, но она так же хороша при выполнении более простых, ориентированных на команды операций. Настоящее изящество оболочки заключается в том, что одну и ту же задачу можно успешно решить, применяя любой из этих двух подходов.
Просто сценарий
Следующая функция примет имя компьютера из командной строки в виде строки или в свойстве ComputerName передаваемого объекта; она также найдет информацию об операционной системе и BIOS каждого компьютера, используя Windows Management Instrumentation (WMI):
function Get-Inventory
{
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[string] $computername
)
Process {
$os = gwmi win32_operatingsystem -computername $computername
$bios = gwmi win32_bios -computername $computername
$obj = new-object psobject
$obj | add-member noteproperty ComputerName $computername
$obj | add-member noteproperty OSBuild ($os.buildnumber)
$obj | add-member noteproperty SPVersion ($os.servicepackmajorversion)
$obj | add-member noteproperty BIOSSerial ($bios.serialnumber)
Write-output $obj
}
}
Обратите внимание, что круглые скобки заставляют оболочку выполнять выражения — такие, как получение и передача свойства BuildNumber из объекта в переменную $os, — и возвращать результат этого выражения в виде значения третьего параметра командлета Add-Member.
Я также могу использовать эту функцию для загрузки по конвейеру статических имен компьютеров:
'localhost','server2' | Get-Inventory
Или для передачи содержимого текстового файла, содержащего в каждой строке по одному имени компьютера:
Get-Content names.txt | Get-Inventory
Или даже для получения объектов-компьютеров из Active Directory, изменения свойства Name на ComputerName и передачи результата по конвейеру:
Import-Module ActiveDirectory
Get-ADComputer –filter * | Select-Object @{Label='ComputerName';Expression={$_.Name}} | Get-Inventory
Между прочим, я использую фигурные скобки для инкапсуляции исполняемого кода. Знак подстановки $_ представляет объект, передаваемый по конвейеру в командлет Select-Object. Все полученные результаты аккуратно оформляются в виде таблицы с четырьмя столбцами. Я могу легко перенаправить вывод в файл, на принтер или в сетку, или даже отфильтровать и отсортировать результаты перед отображением. Например, так:
Get-Content names.txt | Get-Inventory | Where { $_.BuildNumber –eq 7600 } | Sort ComputerName
Еще раз:фигурные скобки инкапсулируют блок исполняемого кода — выражения, которое нужно отфильтровать, а знак подстановки $_ представляет поступающий по конвейеру объект.
Команда во всей красе
С приведенным сценарием все нормально, но он довольно сложен, потому что написан в «программерском» стиле, который отпугивает большинство администраторов. То же самое можно было бы сделать одной, но несколько усложненной командой:
Get-WmiObject Win32_OperatingSystem -computername (get-content names.txt) |
Select-object @{Label="ComputerName";Expression={$_.__SERVER}},
@{Label="OSBuild";Expression={$_.BuildNumber}},
@{Label="SPVersion";Expression={$_.ServicePackMajorVersion}},
@{Label="BIOSSerial";Expression={(gwmi win32_bios -comp $_.__server).serialnumber}}
Здесь много чего происходит и вот расшифровка:
- Сначала выполняется Get-WmiObject для получения объекта Win32 _OperatingSystem для компьютеров с указанными именами. Регулярные читатели моей колонки в курсе, что объекты, возвращенные Get-WmiObject, всегда включают свойство __SERVER , которое содержит имя компьютера, от которого поступили WMI-объекты.
- WMI-объекты по конвейеру передаются в Select-Object. Я использую четыре хеш-таблицы для определения четырех свойств: ComputerName, OSBuild, SPVersion и BIOSSerial. Каждая хеш-таблица определяет метку (она будет позже использоваться как заголовок столбца при выводе) и выражение. Хеш-таблица создается оператором @array, за которым следует определение метки и выражения в фигурных скобках. Эти фигурные скобки содержат исполняемый код, который определяет выражение в хеш-таблице.
- В первых трех столбцах выражение просто проставляет существующее свойство объекта; по сути, я изменяю имя свойства.
- В четвертом столбце мое выражение фактически выполняет второе WMI-обращение к тому же серверу. Оно извлекает имя компьютера из свойства __SERVER. Видите, как все WMI-обращение заключено в круглые скобки? Они вынуждают его выполняться в первую очередь. Любой объект, полученный в результате выполнения этого выражения, будет вставлен вместо блока со скобками. Точка после закрывающей круглой скобки позволяет мне получить доступ к свойствам результирующего объекта, так что в четвертом столбце происходит обращение к свойству SerialNumber.
В известной степени этот синтаксис труднее для чтения, чем сценарий в начале статьи. Он компактный и в нем много пунктуации. Это одна из тех вещей, которую можно использовать как шаблон и изменять ее для решения тех или иных задач. Если вам не удается разобраться, почему ваша команда не работает, разместите вопрос в моем блоге на сайте ConcentratedTech.com и я помогу вам выяснить причину.
Не называйте это сценарием
Дело в том, что Windows PowerShell не обязательно использовать как язык сценариев. Команда, которую я демонстрировал, может показаться сложной, но она нисколько не сложнее, чем некоторые из навороченных команд, которые администраторы ваяли в старой оболочке Cmd.exe. Как только вы привыкнете к синтаксису — должен признать, на это потребуется какое-то время, команда покажется намного менее сложной, чем написание полноценного сценария или функции.
Так что не позволяйте ярлыку «язык сценариев» отпугнуть вас от оболочки Windows PowerShell. Она «сценарна» только в том случае, когда вам этого хочется.
Связанные материалы