Windows PowerShellПересмотр понятия конвейера

Дон Джонс (Don Jones)

О том, насколько необычной, новой и захватывающей является Windows PowerShell, было сказано много, несмотря на то, что эта среда основана на концепциях интерфейса командной строки, известных в течение десятилетий в основном в операционных системах на базе UNIX и Linux. Но распространенная терминология, которой совместно со своими потомками пользуется Windows PowerShell, может легко

отвлечь от подлинной гибкости и уникальности среды Windows PowerShell™ и ее выдающейся приспособленности к среде Windows®.

Одним из наиболее часто обсуждаемых компонентов Windows PowerShell является ее конвейер, но, к сожалению, он является также одним из самых неправильно понимаемых компонентов. Это объясняется тем, что он основан на терминологии, определения для которой были созданы в начале 1970-х гг. и которая в то время представляла совершенно другие, менее мощные функции.

Происхождение каналов

Первой из когда-либо созданных оболочек UNIX была оболочка shell Томпсона, которая была крайне примитивна и отличалась только наличием базовых элементов языка написания сценариев, не имевшего никаких переменных. У shell была преднамеренно скромная структура, поскольку ее единственная реальная цель заключалась в выполнении программ. Однако она ввела в обиход ключевую концепцию, оказавшую положительное влияние на другие оболочки того времени: концепцию конвейеров. Используя символы < и >, оболочке можно было передать инструкцию по направлению входных и выходных данных в другие команды и из них. Теперь пользователь мог, например, направить результат работы команды в файл.

Позднее этот синтаксис был расширен с тем, чтобы выходные данные одной команды можно было передавать с помощью конвейера на вход другой команды, что дает возможность при выполнении сложных задач объединять в цепочку длинные последовательности команд. К 4-й версии shell символ вертикальной черты «|» был принят для обозначения передачи по конвейеру и вследствие этого стал известен как символ конвейера. Даже в самых ранних версиях MS-DOS® были реализованы базовые операции с конвейером с использованием этих символов, что позволяло пользователю, например, передавать с помощью конвейера выходные данные команды type на вход команды more, обеспечивая постраничное отображение длинных текстовых файлов.

Хотя к моменту выпуска 6 версии UNIX в 1975 году было широко распространено мнение, что оболочка shell Томпсона не отвечает предъявляемым к ней требованиям, концепция конвейеров прочно внедрилась в сознание разработчиков оболочек и пользователей и была перенесена в ряд технологий, используемых до сегодняшнего дня.

Передача текста через конвейер

Почти все оболочки по сути ограничены своей текстовой природой. В операционных системах на базе UNIX это, фактически, является не ограничением, а отражением того, как работает сама операционная система. Почти все ресурсы в UNIX можно представить в виде некоторого типа файла, что означает, что способность передавать текст с помощью конвейера от одной команды к другой обеспечивает значительную мощность и гибкость.

Однако, когда доходит до управленческой информации, текст является очевидным ограничением. Например, если бы я представил вам список служб, выполняющихся на компьютере с операционной системой Windows, вы почти наверняка смогли бы его понять. Возможно, я поместил бы имя службы в первом столбце, а режим ее запуска — во втором. Мощный человеческий мозг незаметно и мгновенно анализирует или переводит изображенный текст в значащую информацию, с которой можно работать. Компьютеры, однако, не настолько сообразительны: чтобы компьютер сделал что-нибудь осмысленное с этим списком, потребовалось бы сообщить ему, возможно, что в первом столбце содержатся символы с 1-го по 20-й, а что символы от 22-го до 40-го образуют второй столбец и т.д..

Годами такой тип анализа текстового файла являлся единственным способом, которым администраторы могли объединять несколько команд в цепочку. Фактически, языки написания сценариев, такие как VBScript и Perl, превосходно справляются с манипуляцией строками главным образом по той причине, что им необходима способность принимать текстовый вывод от одной программы или команды, затем реструктурировать эти выходные данные в некоторый вид данных, удобный для использования в какой-либо последующей задаче. Например, я писал задания VBScript, которые принимают текстовый вывод команды Dir, анализируют в этом выводе имена и даты, затем перемещают старые, неиспользуемые файлы в архив. Анализ строк крайне сложен, поскольку исключения (вариации во входных данных) встречаются почти всегда, что требует повторного выполнения логики сценария, чтобы обработать все возможные перестановки.

Для написания административных сценариев или автоматизации в среде Windows анализ строк пригоден в меньшей степени. Это объясняется тем, что Windows сама по себе не хранит большие объемы информации в удобном для доступа текстовом формате. Вместо этого в ней используются ориентированные на данные хранилища, например, Active Directory®, реестр Windows и хранилище сертификатов, поэтому авторы сценариев должны использовать сначала одно средство для создания некоторого вида текстового вывода, а затем — сценарий для анализа этого текста и каких-либо операций над ним.

С объектами работать проще

Разработчики программного обеспечения Windows всегда поступали несколько проще. Исходно Майкрософт разработала COM специально для представления сложных внутренних рабочих компонентов Windows в удобном для использования виде. Сегодня Microsoft® .NET Framework продолжает выполнять эту же задачу — представляет внутренние рабочие компоненты программного обеспечения в стандартизованном виде.

В общем, как COM, так и .NET представляют элементы в виде объектов. (Разработчик программного обеспечения мог бы возразить против этого упрощения, но для нашего обсуждения такого упрощения вполне достаточно.) Все эти объекты имеют разные типы членов. Для наших целей наиболее интересны свойства и методы объектов. Свойство, по существу, некоторым способом описывает объект или изменяет объект или его поведение. Например, объект-служба мог бы иметь свойство, содержащее имя службы, и другое свойство, содержащее режим запуска службы. Методы вызывают выполнение объектом некоторого действия. Объект-служба мог бы иметь, например, методы с именами Stop, Start, Pause и Resume, представляющие различные действия, которые можно проделать со службой.

При программировании (или написании сценариев) ссылки на члены объекта выполняются с использованием точки. Объекты часто присваиваются переменным, что дает возможность манипулировать объектом физически. Например, если имеется служба, присвоенная переменной $service, эту службу можно остановить с помощью синтаксиса $service.Stop. Или можно извлечь отображаемое имя службы, отобразив $service.Name.

Объекты в конвейере

Поскольку Windows является большой и сложной операционной системой, и поскольку ее данные управления не хранятся в представлениях текстового стиля, старые приемы оболочек не очень-то для нее подходят. Например, предположим, что имеется средство командной строки с название SvcList.exe, создающее отформатированный список служб и их режимов запуска. В оболочке командной строки Windows — оболочке, которая корнями уходит глубоко в оболочку MS-DOS, которой несколько десятков лет — можно было бы выполнить, например, такую команду:

SvcList.exe | MyScript.vbs 

Эта инструкция извлекает список служб и передает по каналу этот список в файл VBScript. Следовало бы написать файл VBScript для анализа форматированного списка и выполнить то, что от него требуется — может быть, вывести все службы, режимом запуска которых является Disabled. Для выполнения этой задачи потребуется время. В конечном счете, проблема заключается в уникальности вывода SvcList.exe — эта команда не использует некоторый общий формат, который позволил бы другим командам без труда воспринять ее выходные данные с пользой для себя.

Объекты, однако, предоставляют этот общий формат, и именно поэтому конвейер Windows PowerShell работает с объектами в целом, не только с текстом. При выполнении командлета типа Get-WMIObject выполняется создание группы (или коллекции, в программистских терминах) объектов. Каждый объект поступает в полном составе, со свойствами и методами, позволяющими им манипулировать. Если объекты передаются по конвейеру в командлет Where-Object, их можно отфильтровывать, чтобы отображались только требуемые объекты. Командлету Where-Object не требуется анализировать никакой текст, потому что он не получает никакого текста — он получает объекты. Пример:

Get-WMIObject Win32_Service | Where-Object {$_.StartMode -eq “Disabled” }

Или, если предпочтительнее краткий синтаксис, обеспечиваемый псевдонимами:

gwmi Win32_Service | where {$_.StartMode -eq “Disabled” }

Что интересно, так это то, что Windows PowerShell всегда передает объекты по конвейеру. И только в конце конвейера, когда больше некому передавать объекты, оболочка создает текстовое представление объектов с помощью встроенных правил форматирования. Рассмотрим следующий пример:

Gwmi Win32_Service | where {$_.StartName –eq “LocalSystem” } | select Name,StartMode

Этот набор из трех командлетов получает все службы из моего локального компьютера, отфильтровывает все те, которые не используют для входа в систему учетную запись LocalSystem, а затем передает остаток командлету Select-Object, который выводит только два свойства — Name и StartMode, которые были запрошены. Результатом является простой отчет, содержащий службы, входящие в систему в качестве LocalSystem (возможно, с целью проверки безопасности).

Поскольку все командлеты совместно используют общий формат данных — объекты, они обмениваются данными друг с другом без выполнения сложного анализа строк. А так как у Windows PowerShell имеется встроенная способность создавать текстовое представление объекта, на выходе этого канала наверняка будет текстовый вывод, доступный для чтения человеку. На рис. 1 приведен пример результирующего вывода.

Рис. 1 Текстовый вывод, созданный набором объединенных конвейером командлетов, передающих объекты

Рис. 1** Текстовый вывод, созданный набором объединенных конвейером командлетов, передающих объекты **

Конвейеры – это здорово

Причина того, что передача по конвейерам в Windows PowerShell настолько изумительна, заключается в том, что все элементы в Windows PowerShell являются объектами, укомплектованными свойствами и методами, которые можно использовать. С технической точки зрения даже текстовый файл — это набор объектов-строк; каждая строка в файле выступает в качестве уникального и независимого объекта. Например, создадим текстовый файл (с помощью «Блокнота») с названием C:\Computers.txt. Заполним этот файл текстом и запустим в Windows PowerShell следующую команду:

Get-Content C:\Computers.txt | Select-Object Length | Format-List

Или снова, если желателен меньший объем ввода, можно использовать псевдонимы:

gc C:\Computers.txt | select Length | fl

Этот код обеспечивает получение списка, в котором длина каждой строки текста в файле указана количеством символов. Get-Content извлекает объекты-строки из файла, Select-Object получает свойство Length каждого из них, затем Format-List создает хорошо оформленный, доступный для чтения текст. Хотя приведенный пример не является практичным средством для использования администраторами, он иллюстрирует, что даже такой простой элемент, как строка текста, в Windows PowerShell является объектом.

Возможность передавать объекты по конвейеру от командлета к командлету — или даже от командлета в сценарий — обеспечивает создание невероятно мощных «средств из одной строки». Это простые строки командлетов, соединенные в длинный конвейер, изменяющий набор объектов, чтобы в конце предоставить то, что вам требуется. Практически без какого-либо написания сценария или программирования командлеты Windows PowerShell, образующие соответствующий конвейер, могут обеспечить замечательные результаты.

Поддержка будущих поколений

Тот факт, что будущие серверные продукты Майкрософт также создаются на базе Windows PowerShell, еще больше расширяет эти функциональные возможности. При внедрении нового компьютера для Exchange Server 2007, например, можно использовать Windows PowerShell для извлечения всех почтовых ящиков, отфильтровывания всех тех, которые не относятся к офису, в котором будет расположен новый почтовый сервер, и последующем перемещении оставшихся почтовых ящиков на новый сервер — все это выполняется посредством одной строки текста без написания сценария. Группа Exchange Server 2007 опубликовала длинный список мощных средств из одной строки. Они реально демонстрируют мощь конвейера и административные задачи, которые можно выполнить с его помощью.

Тонкость, связанная с Windows PowerShell, состоит в необходимости осознания того, что, несмотря на то, что оболочка построена на давно сформулированных принципах и философии из мира UNIX, это новое средство уникальным образом соответствует потребностям администрирования в Windows. Не дайте ввести себя в заблуждение общности терминологии и не думайте, что Windows PowerShell всего лишь переделка оболочки UNIX для Windows. Оболочка Windows PowerShell содержит самые современные новые концепции, в которых используются преимущества платформы Windows, и тесно связана с принципами работы операционной системы Windows.

Дон Джонс (Don Jones) обладает званием MVP по Windows PowerShell и является автором Windows PowerShell 101 (ScriptingTraining.com). Связаться с Доном можно через его веб-узел www.ScriptingAnswers.com.

© 2008 Корпорация Майкрософт и компания CMP Media, LLC. Все права защищены; полное или частичное воспроизведение без разрешения запрещено.