Когда бы я ни рассказывал окружающим о Windows PowerShell — будь это на конференции, в общедоступной группе новостей Windows PowerShell или даже на моем веб-узле, каждый раз мне попадаются администраторы, сообщающие, что они «не торопятся» изучать Windows PowerShell. Почему? Чаще всего в качестве причины они сообщают о том,
что именно сейчас у них нет времени учиться написанию сценариев.
Это широко распространенное ощущение. Мы, администраторы, всегда очень заняты, и у нас действительно не хватает времени на изучение новых технологий. Но нам необходимо двигаться вперед, изучать новое программное обеспечение, например Windows Vista®, Windows Server® 2008 и Exchange Server 2007, и только так мы можем оставаться на верхнем уровне технологий, крайне важных для их работы. А Windows PowerShell™ представляет собой существенную часть этих технологий.
Еще одна причина, по которой откладывается изучение написания сценариев в Windows PowerShell (ее часто приводят администраторы), она заключается в том, что они, как сказал один администратор, «боятся стать программистами». Что же, в этом вопросе я могу вам помочь. Возможно, вы удивитесь, узнав, что с помощью Windows PowerShell можно делать поистине удивительные вещи, не написав ни строчки кода.
Подготовка для передачи по конвейеру
Я писал ранее о крайне гибком и мощном объектно-ориентированном конвейере, используемом в Windows PowerShell. (Даже если слова «объектно-ориентированный» вызывают у вас подозрения о том, что я направляюсь в сторону программирования, не убегайте.) Одним из моих любимых качеств конвейера является возможность использовать его в интерактивном режиме. Конвейер мгновенно выдает вам результаты и дает возможность уточнять их, позволяя вам получить в точности то, что требуется. Например, предположим, что для нескольких удаленных компьютеров требуется получить описание свободного пространства на диске. Далее, пусть имена этих компьютеров перечислены в текстовом файле с именем C:\Computers.txt. Это просто обычный текстовый файл, содержащий по одному имени компьютера в строке, — никаких сложностей, подобных базам данных.
Для начала я проверю, можно ли извлечь эту информацию из локального компьютера. В конце концов, если я справлюсь с этим на одном компьютере, выполнение такой же задачи на нескольких компьютерах не должно вызвать трудностей. Напомню, что в этой процедуре не должен участвовать сценарий! Я намерен выполнять все операции в оболочке в интерактивном режиме, получая результаты сразу после нажатия клавиши ВВОД.
В задачах такого рода есть одна хитрость. Возможно, каждый раз, когда требуется получить список с управляющей информации с удаленных компьютеров, вы пользуетесь WMI (инструментарием управления Windows®). Теперь предположим, для целей данного примера, что я знаю только то, что мне требуется использовать WMI. Поэтому я обращаюсь к функции поиска Live Search и в качестве выражения поиска ввожу «windows wmi free disk space». Появляется несколько результатов, среди которых есть фраза «Win32_LogicalDisk». Это мне кажется похожим на класс WMI, и, возможно, это то, что я ищу. Я даже не даю себе труда щелкнуть какой-либо из этих результатов поиска. Вместо этого я ввожу «Win32_LogicalDisk» в качестве нового выражения поиска, и первый из результатов ссылается на страницу с документацией по Win32_LogicalDisk, находящуюся на веб-узле MSDN® по адресу (msdn2.microsoft.com/aa394173.aspx). Поэтому я перехожу к этой странице и вижу, что одно из свойств этого класса называется FreeSpace, что звучит многообещающе.
Поиск командлета
Для следующего этапа мне требуется найти командлет, который извлечет для меня свойства класса WMI. Одним из примечательных качеств оболочки Windows PowerShell являются ее фантастические встроенные функции самораскрытия — оболочка облегчает получение информации о своих возможностях. Поэтому для выяснения того, что оболочке известно о работе с WMI, я ввожу «Help *wmi*». В результатах, показанных на рис. 1, содержится псевдоним Gwmi и командлет, на который он указывает — Get-WMIObject. По существу, для доступа к одному и тому же набору функций имеется два способа, т.е. нет необходимости в принятии твердого решения об использовании одного из них. Поскольку они делают одно и то же, и Gwmi набирается быстрее, я использую следующий вариант
Рис. 1 Что оболочке известно о работе с WMI
PS C:\> gwmi win32_logicaldisk
Отмечу, что для Windows PowerShell не важен регистр — она знает, что у администраторов нет времени на всякую суету вроде нажатия клавиши Shift.
В результаты работы этой команды, показанные на рис. 2, входят все мои пять локальных дисков и их свойства FreeSpace, которые, как оказалось, приводятся выраженными в байтах. Кроме этого, выведено свойство DriveType для каждого из этих дисков, и на моем компьютере я вижу значения 2, 3 и 5.
Рис. 2 Все мои локальные диски и их свойства FreeSpace
Очистка данных
В этом пункте у меня две проблемы. Во-первых, мне не важны все прочие свойства, мне требуется только FreeSpace. Во-вторых, мне не нужна информация о свободном пространстве на оптических дисках, съемных дисках или сетевых дисках; меня заботят только локальные жесткие диски. Возможно, свойство DriveType поможет различить диски. Я возвращаюсь в веб-обозреватель и вижу, что в документации содержится таблица, поясняющая, чему соответствуют разные значения DriveType. Мне требуются те, которые имеют значение DriveType, равное 3, означающее, что это локальный жесткий диск. Хотя я никогда ранее не выполнял этого, решаю посмотреть, может ли команда Gwmi выполнить работу по фильтрации. Выполнив команду Help Gwmi –full, получаю подробные сведения о работе команды, включая несколько примеров. Обнаруживаю ключ, который кажется полезным, –filter, и поэтому решаю выполнить следующий вариант команды.
Командлет месяца
Возможно, вы использовали Get-Content для чтения содержимого текстового файла. Он рассматривает каждую строку файла в качестве объекта [string] и передает эти объекты в конвейер для обработки другими командлетами. Но у Get-Content имеется ряд ключей, которые делают его более гибким: ключ –readCount, например, позволяет указать, какое количество объектов [string] передается в конвейер за один прием (по умолчанию передаются все), а ключ –totalCount управляет общим числом строк, считываемых из файла. Оба эти ключа удобны при работе с действительно большими файлами, когда из соображений производительности может возникнуть потребность отказаться от обработки всего файла за один прием.Есть еще один ключ, который вы сочтете удобным. Ключ –encoding позволяет правильно читать обширный набор типов кодировки файлов, включая юникод, ASCII, UTF7, UTF8 и многие другие. Для просмотра полного списка поддерживаемых типов кодировки выполните команду help gc (gc — псевдоним для Get-Content).
gwmi win32_logicaldisk -filter "drivetype = 3"
Сработало! Теперь в моем списке дисководов содержатся только локальные несъемные диски. Значит, вторая проблема решена; теперь необходимо разобраться с первой — избавиться от всех не интересующих меня свойств.
Запускаю Get-Command для получения списка всех командлетов Windows PowerShell и, в конце концов, наталкиваюсь на Select-Object. В описании сказано, что этот командлет «Выбирает указанные свойства объекта или набора объектов.» Поэтому я пытаюсь сделать следующее.
gwmi win32_logicaldisk -filter "drivetype = 3" | select freespace
Передавая по конвейеру результаты работы Gwmi в Select (псевдоним для Select-Object), я могу получить именно то свойство, которое мне требуется. Стоп, ошибочка вышла. Эти результаты не слишком хороши, поскольку все, что я получил, –– это список чисел — мне больше не известно, какое из перечисленных свободных пространств какому диску соответствует. Поэтому я возвращаюсь к документации и вижу, что свойство DeviceID содержит букву диска. Быстро переделываю свою команду и повторяю попытку.
gwmi win32_logicaldisk -filter "drivetype = 3" | select deviceid,freespace
Отлично! И, поскольку в списке имеются только два свойства, оболочке удается поместить информацию в аккуратную таблицу. (В следующем месяце я объясню, когда Windows PowerShell предпочитает списки, а когда — таблицы.)
Вычисления
Информация о свободном пространстве извлечена, но она представлена в байтах, а это в действительности не так удобно, как в мегабайтах или гигабайтах. Возможно, мне требуется не само свойство FreeSpace, а, скорее, значение, вычисленное на основе свойства FreeSpace. Командлет ForEach-Object (или один из множества его псевдонимов, например %) может с этим помочь. Этот командлет позволяет использовать специальную переменную, $_, для ссылки на текущий логический диск, что дает доступ ко всем свойствам диска по отдельности и позволяет выполнять некоторые математические операции. Далее идет измененная команда.
gwmi win32_logicaldisk -filter "drivetype = 3" | % { $_.deviceid; $_.freespace/1GB }
Я всего лишь удалил отсюда Select и заменил его псевдонимом для ForEach-Object (%). Этому командлету требуется только, чтобы ему сообщили, что следует сделать с каждым получаемым им Win32_LogicalDisk, и здесь указано, что требуется получить свойство DeviceID и пересчитать свойство FreeSpace в гигабайты — Windows PowerShell «знает», что такое KB, MB и GB, поэтому результат выдается в гигабайтах.
Несколько компьютеров
Теперь, когда эта процедура работает для одного компьютера, пора использовать ее для нескольких систем. Мне известно, как получить содержимое текстового файла. Это делается точно так же, как во времена MS-DOS® — с помощью команды Type, которая в Windows PowerShell, оказывается, является псевдонимом для Get-Content.
Type c:\computers.txt
Требуется сделать следующее — взять все эти компьютеры и для каждого из них выполнить уже разработанную команду WMI. Фраза «для каждого» должна напомнить вам о командлете — а именно, о ForEach-Object. Поэтому просто перейдем к завершающей демонстрации, как говорят в телевизионных шоу, обновляющих дома, и посмотрим на мою окончательную команду.
type c:\computers.txt | % { $_;
gwmi –computername $_ win32_logicaldisk -filter "drivetype=3" | % { $_.deviceid; $_.freespace/1GB} }
Ужасная, верно? Благодаря тому, что использовались исключительно псевдонимы, а не имена командлетов, прочесть это тяжело. Однако, это крайне просто расшифровывается, если ее разделить на маленькие порции.
- Я начинаю с «печати» содержимого моего текстового файла.
- Это содержимое передается по конвейеру в командлет ForEach-Object.
- ForEach-Object выводит текущий результат с помощью переменной $_. (Это имя текущего компьютера.)
- Затем ForEach-Object выполняет мою команду WMI, в которой содержится еще один вызов командлета ForEach-Object.
Замена имен-псевдонимов именами командлетов может облегчить понимание. Поэтому далее идет та же команда, но на этот раз написаны имена командлетов, и команда разделена на отдельные строки для удобства изучения каждого фрагмента.
Get-Content C:\Computers.txt |
ForEach-Object {
$_; Get-WMIObject –computername $_
Win32_LogicalDisk -filter "DriveType=3" |
ForEach-Object {
$_.DeviceID; $_.FreeSpace/1GB
}
}
Результаты, не будучи привлекательными, но оставаясь функциональными, показаны на рис. 3.
Рис. 3 Окончательные результаты
Нет необходимости в сценариях
Смысл этого анализа заключается в демонстрации использования Windows PowerShell без написания какого-либо сценария. Имея эти несколько примеров и изучив немного саму оболочку Windows PowerShell, вы действительно сможете найти те элементы, которые необходимы для выполнения любой поставленной вами задачи.
Итог состоит в том, что оболочка Windows PowerShell никуда не исчезнет. Может быть, уже сейчас стоит начинать учиться пользоваться ею? Возможно, вы будете удивляться, как до сих пор жили без нее — и, определенно, слово «сценарий» не удержит вас от того, чтобы приступить к ее использованию.
Автор: Дон Джонс (Don Jones) — ведущий разработчик сценариев в компании SAPIEN Technologies и преподаватель на ScriptingTraining.com.
Взято с Technet Magazine