Командная строка и сценарии Windows

Конвейеризация и управление выводом команд Windows PowerShell

Разбить на страницы
Показывать лекцию целиком

Конвейеризация и управление выводом команд Windows PowerShell

Ранее в лекции 2 мы рассматривали понятие конвейеризации (или композиции) команд интерпретатора Cmd.exe, когда выходной поток одной команды перенаправлялся во входной поток другой, объединяя тем самым две команды вместе. Подобные конвейеры команд используются в большинстве оболочек командной строки и являются средством, позволяющим передавать информацию между разными процессами.

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

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

Конвейеризация объектов в PowerShell

Конвейер в PowerShell – это последовательность команд, разделенных между собой знаком | (вертикальная черта). Каждая команда в конвейере получает объект от предыдущей команды, выполняет определенные операции над ним и передает следующей команде в конвейере. С точки зрения пользователя, объекты упаковывают связанную информацию в форму, в которой информацией проще манипулировать как единым блоком и из которой при необходимости извлекаются определенные элементы.

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

При передаче по конвейеру объектов этой проблемы не возникает, здесь нужная информация извлекается из элемента конвейера простым обращением к соответствующему свойству объекта. Однако теперь возникает новый вопрос: каким образом узнать, какие именно свойства есть у объектов, передаваемых по конвейеру? Ведь при выполнении того или иного командлета мы на экране видим только одну или несколько колонок отформатированного текста. Например, запустим командлет Get-Process, который выводит информацию о запущенных в системе процессах:

PS C:\> Get-Process

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    158      11    45644      22084   126   159.69   2072 AcroRd32
     98       5     1104        284    32     0.10    256 alg
     39       1      364        364    17     0.26   1632 ati2evxx
     57       3     1028        328    30     0.38    804 atiptaxx
    434       6     2548       3680    27    21.96    800 csrss
     64       3      812        604    29     0.22   1056 ctfmon
    364      11    14120       9544    69    11.82    456 explorer
     24       2     1532       2040    29     5.34   2532 Far

Фактически на экране мы видим только сводную информацию (результат форматирования полученных данных), а не полное представление выходного объекта. Из этой информации не понятно, сколько точно свойств имеется у объектов, генерируемых командой Get-Process, и какие имена имеют эти свойства. Например, мы хотим найти все "зависшие" процессы, которые не отвечают на запросы системы. Можно ли это сделать с помощью командлета Get-Process, какое свойство нужно проверять у выводимых объектов?

Для ответа на подобные вопросы нужно, прежде всего, научиться исследовать структуру объектов PowerShell, узнавать, какие свойства и методы имеются у этих объектов.

Просмотр структуры объектов

Для анализа структуры объекта, возвращаемого определенной командой, проще всего направить этот объект по конвейеру на командлет Get-Member (псевдоним gm ), например:

PS C:\> Get-Process | Get-Member

   TypeName: System.Diagnostics.Process

Name                    MemberType     Definition
----                    ----------     ----------
Handles                 AliasProperty  Handles = Handlecount
Name                    AliasProperty  Name = ProcessName
NPM                     AliasProperty  NPM = NonpagedSystemMemorySize
PM                      AliasProperty  PM = PagedMemorySize
VM                      AliasProperty  VM = VirtualMemorySize
WS                      AliasProperty  WS = WorkingSet
. . .
Responding              Property       System.Boolean Responding {get;}
. . .

Здесь мы видим имя .NET-класса, экземпляры которого возвращаются в ходе работы исследуемого командлета (в нашем примере это класс System.Diagnostic.Process), а также полный список элементов объекта (в частности, интересующее нас свойство Responding, определяющего "зависшие" процессы). При этом на экран выводится очень много элементов, просматривать их неудобно. Командлет Get-Member позволяет перечислить только те элементы объекта, которые являются его свойствами. Для этого используется параметр MemberType со значением Properties:

PS C:\> Get-Process | Get-Member -MemberType Property

   TypeName: System.Diagnostics.Process

Name                       MemberType Definition
----                       ---------- ----------
BasePriority               Property   System.Int32 BasePriority {get;}
Container                  Property   System.ComponentModel.IContainer...
EnableRaisingEvents        Property   System.Boolean EnableRaisingEvents...
ExitCode                   Property   System.Int32 ExitCode {get;}
ExitTime                   Property   System.DateTime ExitTime {get;}
Handle                     Property   System.IntPtr Handle {get;}
HandleCount                Property   System.Int32 HandleCount {get;}
HasExited                  Property   System.Boolean HasExited {get;}
Id                         Property   System.Int32 Id {get;}
MachineName                Property   System.String MachineName {get;}
. . . 
Responding                 Property   System.Boolean Responding {get;}
. . .

Как мы видим, процессам операционной системы соответствуют объекты, имеющие очень много свойств, на экран же при работе командлета Get-Process выводятся лишь несколько из них (способы отображения объектов различных типов задаются конфигурационными файлами в формате XML, находящимися в каталоге, где установлен файл powershell.exe).

Теперь, когда мы знаем, какие свойства имеют объекты, передаваемые по конвейеру, перейдем к рассмотрению наиболее часто используемых операций над элементами конвейера: фильтрации и сортировки.

Фильтрация объектов в конвейере

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

Например, для вывода информации о "зависших" процессах (объекты, возвращаемые командлетом Get-Process, у которых свойство Responding равно False ) можно использовать следующий конвейер:

Get-Process | Where-Object {-not $_.Responding}

Другой пример – оставим в конвейере только те процессы, у которых значение идентификатора (свойство Id ) больше 1000:

Get-Process | Where-Object {$_.Id -gt 1000}

В блоках сценариев командлета Where-Object для обращения к текущему объекту конвейера и извлечения нужных свойств этого объекта используется специальная переменная $_, которая создается оболочкой PowerShell автоматически. Данная переменная используется и в других командлетах, производящих обработку элементов конвейера.

Условие проверки в Where-Object задается в виде блока сценария – одной или нескольких команд PowerShell, заключенных в фигурные скобки {}. Результатом выполнения данного блока сценария должно быть значение логического типа: True (истина) или False (ложь). Как можно понять из примеров, в блоке сценария используются специальные операторы сравнения.

Замечание

В PowerShell для операторов сравнения не используются обычные символы > или <, так как в командной строке они обычно означают перенаправление ввода/вывода.

Основные операторы сравнения приведены в табл. 17.1.

Операторы сравнения в PowerShell
Оператор Значение Пример (возвращается значение True)
-eq равно 10 -eq 10
-ne не равно 9 -ne 10
-lt меньше 3 -lt 4
-le меньше или равно 3 –le 4
-gt больше 4 -gt 3
-ge больше или равно 4 -ge 3
-like сравнение на совпадение с учетом подстановочного знака в тексте "file.doc" –like "f*.doc"
-notlike сравнение на несовпадение с учетом подстановочного знака в тексте "file.doc" –notlike "f*.rtf"
-contains содержит 1,2,3 –contains 1
-notcontains не содержит 1,2,3 –notcontains 4

Операторы сравнения можно соединять друг с другом с помощью логических операторов (см. табл. 17.2).

Логически операторы в PowerShell
Оператор Значение Пример (возвращается значение True)
-and логическое И (10 -eq 10) –and (1 –eq 1)
-or логическое ИЛИ (9 -ne 10) –or (3 –eq 4)
-not логическое НЕ -not (3 –gt 4)
! логическое НЕ !(3 -gt 4)

Сортировка объектов

Сортировка элементов конвейера – еще одна операция, которая часто применяется при конвейерной обработке объектов. Данную операцию осуществляет командлет Sort-Object: ему передаются имена свойств, по которым нужно произвести сортировку, а он возвращает данные, упорядоченные по значениям этих свойств.

Например, для вывода списка запущенных в системе процессов, упорядоченного по затраченному процессорному времени (свойство cpu ), можно воспользоваться следующим конвейером:

PS C:\> Get-Process | Sort-Object cpu

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
      0       0        0         16     0               0 Idle
     36       2      728         32    23     0.05   1792 klswd
     98       5     1104        764    32     0.09    252 alg
     21       1      164         60     4     0.09    748 smss
     30       2      672        724    27     0.11   1700 WinCinemaMgr
     39       1      364        464    17     0.12   1644 ati2evxx
    163       6     1536       1404    35     0.12   1612 svchost
     55       3     1088        852    27     0.14   1220 svchost
     22       2      504        712    23     0.14    772 winampa
    120       4     2364       1228    35     0.26   1876 svchost
    170       5     4516        796    44     0.27   1260 GoogleToolbarNotifier
    193       5     2916       1488    59     0.29   1040 svchost
     64       3      812       1080    29     0.30   1252 ctfmon
    140       5     3208       1220    41     0.32   1524 spoolsv
    281      14     1764       1688    37     0.34   1120 svchost
     57       3     1028        996    30     0.39    932 atiptaxx
    503      52     7296       3596    51     2.47    836 winlogon
    259       6     1432       1340    19     2.48    880 services
    341       8     3572       1856    40     5.36    892 lsass
    240     158    29536      10388   175     5.58   1780 outpost
    149       4     2940       1108    41     9.29   1248 kav
    398       5    36140      26408   137     9.97   1984 powershell
    375      12    15020      10456    75    14.03   1116 explorer
    376       0        0         36     2    14.97      4 System
    409       6     2500       3192    26    20.10    812 csrss
   1513      54    13528       9800    95    25.78   1156 svchost
    717      75    37432        704   145    56.97   1748 kavsvc
    152       4     2372       2716    38    58.09   2028 wmiprvse
    307      13    10952      27080   173  9128.03   1200 WINWORD

Для сортировки в обратном порядке используется параметр Descending:

PS C:\> Get-Process | Sort-Object cpu -Descending

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    307      13    10956      27040   173  9152.23   1200 WINWORD
    152       4     2372       2716    38    59.19   2028 wmiprvse
    717      75    37432       1220   145    57.15   1748 kavsvc
   1524      54    13528       9800    95    26.13   1156 svchost
    410       6     2508       3224    26    20.62    812 csrss
    376       0        0         36     2    15.11      4 System
    377      13    15020      10464    75    14.20   1116 explorer
    374       5    36484      26828   137    10.53   1984 powershell
    149       4     2940       1108    41     9.34   1248 kav
    240     158    29536      10388   175     5.61   1780 outpost
    344       8     3572       1856    40     5.40    892 lsass
    512      53     7324       3608    51     2.51    836 winlogon
    259       6     1432       1340    19     2.48    880 services
     57       3     1028        996    30     0.39    932 atiptaxx
    281      14     1764       1688    37     0.34   1120 svchost
    140       5     3208       1220    41     0.32   1524 spoolsv
     64       3      812       1080    29     0.30   1252 ctfmon
    193       5     2916       1488    59     0.29   1040 svchost
    170       5     4516        796    44     0.27   1260 GoogleToolbarNotifier
    120       4     2364       1228    35     0.26   1876 svchost
     22       2      504        712    23     0.15    772 winampa
     55       3     1088        852    27     0.14   1220 svchost
     39       1      364        464    17     0.13   1644 ati2evxx
    163       6     1536       1404    35     0.12   1612 svchost
     30       2      672        724    27     0.11   1700 WinCinemaMgr
     21       1      164         60     4     0.09    748 smss
     98       5     1104        764    32     0.09    252 alg
     36       2      728         32    23     0.05   1792 klswd
      0       0        0         16     0               0 Idle

В рассмотренных нами примерах конвейеры состояли из двух командлетов. Это не обязательное условие, конвейер может объединять и большее количество команд, например:

Get-Process | Where-Object {$_.Id -gt 1000} | Sort-Object cpu -Descending

Управление выводом команд в PowerShell

Работая в оболочке PowerShell, мы пока не задумывались, каким образом система формирует строки текста, которые выводятся на экран в результате выполнения той или иной команды (напомним, что командлеты PowerShell возвращают .NET-объекты, которые, как правило, не знают, каким образом отображать себя на экране).

На самом деле в PowerShell имеется база данных (набор XML-файлов), содержащая модули форматирования по умолчанию для различных типов .NET-объектов. Эти модули определяют, какие свойства объекта отображаются при выводе и в каком формате: списка или таблицы. Когда объект достигает конца конвейера, PowerShell определяет его тип и ищет его в списке объектов, для которых определено правило форматирования. Если данный тип в списке обнаружен, то к объекту применяется соответствующий модуль форматирования; если нет, то PowerShell просто отображает свойства этого .NET-объекта.

Также в PowerShell можно явно задавать правила форматирования данных, выводимых командлетами, и подобно командному интерпретатору Cmd.exe перенаправлять эти данные в файл, на принтер или в пустое устройство.

Форматирование выводимой информации

В традиционных оболочках команды и утилиты сами форматируют выводимые данные. Некоторые команды (например, dir в интерпретаторе Cmd.exe) позволяют настраивать формат вывода с помощью специальных параметров.

В оболочке PowerShell вывод форматируют только четыре специальных командлета Format (табл. 17.3). Это упрощает изучение, так как не нужно запоминать средства и параметры форматирования для других команд (остальные командлеты вывод не форматируют).

Командлеты PowerShell для форматирования вывода
Командлет Описание
Format-Table Форматирует вывод команды в виде таблицы, столбцы которой содержат свойства объекта (также могут быть добавлены вычисляемые столбцы). Поддерживается возможность группировки выводимых данных
Format-List Вывод форматируется как список свойств, в котором каждое свойство отображается на новой строке. Поддерживается возможность группировки выводимых данных
Format-Custom Для форматирования вывода используется пользовательское представление (view)
Format-Wide Форматирует объекты в виде широкой таблицы, в которой отображается только одно свойство каждого объекта

Как уже отмечалось выше, если ни один из командлетов Format явно не указан, то используется модуль форматирования по умолчанию, который определяется по типу отображаемых данных. Например, при выполнении командлета Get-Service данные по умолчанию выводятся как таблица с тремя столбцами (Status, Name и DisplayName):

PS C:\> Get-Service

Status   Name               DisplayName
------   ----               -----------
Stopped  Alerter            Оповещатель
Running  ALG                Служба шлюза уровня приложения
Stopped  AppMgmt            Управление приложениями
Stopped  aspnet_state       ASP.NET State Service
Running  Ati HotKey Poller  Ati HotKey Poller
Running  AudioSrv           Windows Audio
Running  BITS               Фоновая интеллектуальная служба пер...
Running  Browser            Обозреватель компьютеров
Stopped  cisvc              Служба индексирования
Stopped  ClipSrv            Сервер папки обмена
Stopped  clr_optimizatio... .NET Runtime Optimization Service v...
Stopped  COMSysApp          Системное приложение COM+
Running  CryptSvc           Службы криптографии
Running  DcomLaunch         Запуск серверных процессов DCOM
Running  Dhcp               DHCP-клиент
...

Для изменения формата выводимых данных нужно направить их по конвейеру соответствующему командлету Format. Например, следующая команда выведет список служб с помощью командлета Format-List:

PS C:\> Get-Service | Format-List

Name                : Alerter
DisplayName         : Оповещатель
Status              : Stopped
DependentServices   : {}
ServicesDependedOn  : {LanmanWorkstation}
CanPauseAndContinue : False
CanShutdown         : False
CanStop             : False
ServiceType         : Win32ShareProcess

Name                : ALG
DisplayName         : Служба шлюза уровня приложения
Status              : Running
DependentServices   : {}
ServicesDependedOn  : {}
CanPauseAndContinue : False
CanShutdown         : False
CanStop             : True
ServiceType         : Win32OwnProcess
. . .

Как мы видим, при использовании формата списка выводится больше сведений о каждой службе, чем в формате таблицы (вместо трех столбцов данных о каждой службе в формате списка выводятся девять строк данных). Однако это вовсе не означает, что командлет Format-List извлекает дополнительные сведения о службах. Эти данные содержатся в объектах, возвращаемых командлетом Get-Service, однако командлет Format-Table, используемый по умолчанию, отбрасывает их, потому что не может вывести на экран более трех столбцов.

При форматировании вывода с помощью командлетов Format-List и Format-Table можно указывать имена свойства объекта, которые должны быть отображены (напомним, что просмотреть список свойств, имеющихся у объекта, позволяет рассмотренный ранее командлет Get-Member ). Например:

PS C:\> Get-Service | Format-List Name, Status, CanStop

Name    : Alerter
Status  : Stopped
CanStop : False

Name    : ALG
Status  : Running
CanStop : True

Name    : AppMgmt
Status  : Stopped
CanStop : False
. . .

Вывести все имеющиеся у объектов свойства можно с помощью параметра *, например:

PS C:\> Get-Service | Format-table *

Перенаправление выводимой информации

В оболочке PowerShell имеются несколько командлетов, с помощью которых можно управлять выводом данных. Эти командлеты начинаются со слова Out, их список можно увидеть следующим образом:

PS C:\> Get-Command out-* | Format-Table Name

Name
----
Out-Default
Out-File
Out-Host
Out-Null
Out-Printer
Out-String

По умолчанию выводимая информация передается командлету Out-Default, который, в свою очередь, делегирует всю работу по выводу строк на экран командлету Out-Host. Для понимания данного механизма нужно учитывать, что архитектура PowerShell подразумевает различие между собственно ядром оболочки (интерпретатором команд) и главным приложением (host), которое использует это ядро. В принципе, в качестве главного может выступать любое приложение, в котором реализован ряд специальных интерфейсов, позволяющих корректно интерпретировать получаемую от PowerShell информацию. В нашем случае главным приложением является консольное окно, в котором мы работаем с оболочкой, и командлет Out-Host передает выводимую информацию в это консольное окно.

Параметр Paging командлета Out-Host, подобно команде more интерпретатора Cmd.exe, позволяет организовать постраничный вывод информации, например:

Get-Help Get-Process –Full | Out-Host -Paging

Сохранение данных в файл

Командлет Out-File позволяет направить выводимые данные вместо окна консоли в текстовый файл. Аналогичную задачу решает оператор перенаправления (>), однако командлет Out-File имеет несколько дополнительных параметров, с помощью которых можно более гибко управлять выводом: задавать тип кодировки файла (параметр Encoding ), задавать длину выводимых строк в знаках (параметр Width ), выбирать режим перезаписи файла (параметры Append, noClobber ). Например, следующая команда направит информацию о зарегистрированных на компьютере службах в файл C:\service.txt, причем данный файл будет записан в формате ASCII:

Get-Process | Out-File -FilePath C:\Process.txt -Encoding ASCII

Печать данных

Данные можно вывести непосредственно на принтер с помощью командлета Out-Printer. При этом печать может производиться как на принтере по умолчанию (никаких специальных параметров для этого указывать не нужно), так и на произвольном принтере (в этом случае отображаемое имя принтера должно быть указано в качестве значения параметра Name ). Например:

PS C:\script> Get-Process | Out-Printer -Name "Xerox Phaser 3500 PCL 6"

Подавление вывода

Командлет Out-Null служит для отбрасывания любых своих входных данных. Это может пригодиться для подавления вывода на экран ненужных сведений, полученных в качестве побочного эффекта выполнения какой-либо команды. Например, при создании каталога командой mkdir на экран выводится его содержимое:

PS C:\> mkdir klop

    Каталог: Microsoft.PowerShell.Core\FileSystem::C:\


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        03.12.2007      1:01            klop

Если вы не желаете видеть эту информацию, то результат выполнения команды mkdir нужно передать по конвейеру командлету Out-Null:

mkdir klop | Out-Null
Страницы:

Конвейеризация и управление выводом команд Windows PowerShell

Ранее в лекции 2 мы рассматривали понятие конвейеризации (или композиции) команд интерпретатора Cmd.exe, когда выходной поток одной команды перенаправлялся во входной поток другой, объединяя тем самым две команды вместе. Подобные конвейеры команд используются в большинстве оболочек командной строки и являются средством, позволяющим передавать информацию между разными процессами.

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

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

Конвейеризация объектов в PowerShell

Конвейер в PowerShell – это последовательность команд, разделенных между собой знаком | (вертикальная черта). Каждая команда в конвейере получает объект от предыдущей команды, выполняет определенные операции над ним и передает следующей команде в конвейере. С точки зрения пользователя, объекты упаковывают связанную информацию в форму, в которой информацией проще манипулировать как единым блоком и из которой при необходимости извлекаются определенные элементы.

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

При передаче по конвейеру объектов этой проблемы не возникает, здесь нужная информация извлекается из элемента конвейера простым обращением к соответствующему свойству объекта. Однако теперь возникает новый вопрос: каким образом узнать, какие именно свойства есть у объектов, передаваемых по конвейеру? Ведь при выполнении того или иного командлета мы на экране видим только одну или несколько колонок отформатированного текста. Например, запустим командлет Get-Process, который выводит информацию о запущенных в системе процессах:

PS C:\> Get-Process

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    158      11    45644      22084   126   159.69   2072 AcroRd32
     98       5     1104        284    32     0.10    256 alg
     39       1      364        364    17     0.26   1632 ati2evxx
     57       3     1028        328    30     0.38    804 atiptaxx
    434       6     2548       3680    27    21.96    800 csrss
     64       3      812        604    29     0.22   1056 ctfmon
    364      11    14120       9544    69    11.82    456 explorer
     24       2     1532       2040    29     5.34   2532 Far

Фактически на экране мы видим только сводную информацию (результат форматирования полученных данных), а не полное представление выходного объекта. Из этой информации не понятно, сколько точно свойств имеется у объектов, генерируемых командой Get-Process, и какие имена имеют эти свойства. Например, мы хотим найти все "зависшие" процессы, которые не отвечают на запросы системы. Можно ли это сделать с помощью командлета Get-Process, какое свойство нужно проверять у выводимых объектов?

Для ответа на подобные вопросы нужно, прежде всего, научиться исследовать структуру объектов PowerShell, узнавать, какие свойства и методы имеются у этих объектов.

Просмотр структуры объектов

Для анализа структуры объекта, возвращаемого определенной командой, проще всего направить этот объект по конвейеру на командлет Get-Member (псевдоним gm ), например:

PS C:\> Get-Process | Get-Member

   TypeName: System.Diagnostics.Process

Name                    MemberType     Definition
----                    ----------     ----------
Handles                 AliasProperty  Handles = Handlecount
Name                    AliasProperty  Name = ProcessName
NPM                     AliasProperty  NPM = NonpagedSystemMemorySize
PM                      AliasProperty  PM = PagedMemorySize
VM                      AliasProperty  VM = VirtualMemorySize
WS                      AliasProperty  WS = WorkingSet
. . .
Responding              Property       System.Boolean Responding {get;}
. . .

Здесь мы видим имя .NET-класса, экземпляры которого возвращаются в ходе работы исследуемого командлета (в нашем примере это класс System.Diagnostic.Process), а также полный список элементов объекта (в частности, интересующее нас свойство Responding, определяющего "зависшие" процессы). При этом на экран выводится очень много элементов, просматривать их неудобно. Командлет Get-Member позволяет перечислить только те элементы объекта, которые являются его свойствами. Для этого используется параметр MemberType со значением Properties:

PS C:\> Get-Process | Get-Member -MemberType Property

   TypeName: System.Diagnostics.Process

Name                       MemberType Definition
----                       ---------- ----------
BasePriority               Property   System.Int32 BasePriority {get;}
Container                  Property   System.ComponentModel.IContainer...
EnableRaisingEvents        Property   System.Boolean EnableRaisingEvents...
ExitCode                   Property   System.Int32 ExitCode {get;}
ExitTime                   Property   System.DateTime ExitTime {get;}
Handle                     Property   System.IntPtr Handle {get;}
HandleCount                Property   System.Int32 HandleCount {get;}
HasExited                  Property   System.Boolean HasExited {get;}
Id                         Property   System.Int32 Id {get;}
MachineName                Property   System.String MachineName {get;}
. . . 
Responding                 Property   System.Boolean Responding {get;}
. . .

Как мы видим, процессам операционной системы соответствуют объекты, имеющие очень много свойств, на экран же при работе командлета Get-Process выводятся лишь несколько из них (способы отображения объектов различных типов задаются конфигурационными файлами в формате XML, находящимися в каталоге, где установлен файл powershell.exe).

Теперь, когда мы знаем, какие свойства имеют объекты, передаваемые по конвейеру, перейдем к рассмотрению наиболее часто используемых операций над элементами конвейера: фильтрации и сортировки.

Фильтрация объектов в конвейере

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

Например, для вывода информации о "зависших" процессах (объекты, возвращаемые командлетом Get-Process, у которых свойство Responding равно False ) можно использовать следующий конвейер:

Get-Process | Where-Object {-not $_.Responding}

Другой пример – оставим в конвейере только те процессы, у которых значение идентификатора (свойство Id ) больше 1000:

Get-Process | Where-Object {$_.Id -gt 1000}

В блоках сценариев командлета Where-Object для обращения к текущему объекту конвейера и извлечения нужных свойств этого объекта используется специальная переменная $_, которая создается оболочкой PowerShell автоматически. Данная переменная используется и в других командлетах, производящих обработку элементов конвейера.

Условие проверки в Where-Object задается в виде блока сценария – одной или нескольких команд PowerShell, заключенных в фигурные скобки {}. Результатом выполнения данного блока сценария должно быть значение логического типа: True (истина) или False (ложь). Как можно понять из примеров, в блоке сценария используются специальные операторы сравнения.

Замечание

В PowerShell для операторов сравнения не используются обычные символы > или <, так как в командной строке они обычно означают перенаправление ввода/вывода.

Основные операторы сравнения приведены в табл. 17.1.

Операторы сравнения в PowerShell
Оператор Значение Пример (возвращается значение True)
-eq равно 10 -eq 10
-ne не равно 9 -ne 10
-lt меньше 3 -lt 4
-le меньше или равно 3 –le 4
-gt больше 4 -gt 3
-ge больше или равно 4 -ge 3
-like сравнение на совпадение с учетом подстановочного знака в тексте "file.doc" –like "f*.doc"
-notlike сравнение на несовпадение с учетом подстановочного знака в тексте "file.doc" –notlike "f*.rtf"
-contains содержит 1,2,3 –contains 1
-notcontains не содержит 1,2,3 –notcontains 4

Операторы сравнения можно соединять друг с другом с помощью логических операторов (см. табл. 17.2).

Логически операторы в PowerShell
Оператор Значение Пример (возвращается значение True)
-and логическое И (10 -eq 10) –and (1 –eq 1)
-or логическое ИЛИ (9 -ne 10) –or (3 –eq 4)
-not логическое НЕ -not (3 –gt 4)
! логическое НЕ !(3 -gt 4)

Сортировка объектов

Сортировка элементов конвейера – еще одна операция, которая часто применяется при конвейерной обработке объектов. Данную операцию осуществляет командлет Sort-Object: ему передаются имена свойств, по которым нужно произвести сортировку, а он возвращает данные, упорядоченные по значениям этих свойств.

Например, для вывода списка запущенных в системе процессов, упорядоченного по затраченному процессорному времени (свойство cpu ), можно воспользоваться следующим конвейером:

PS C:\> Get-Process | Sort-Object cpu

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
      0       0        0         16     0               0 Idle
     36       2      728         32    23     0.05   1792 klswd
     98       5     1104        764    32     0.09    252 alg
     21       1      164         60     4     0.09    748 smss
     30       2      672        724    27     0.11   1700 WinCinemaMgr
     39       1      364        464    17     0.12   1644 ati2evxx
    163       6     1536       1404    35     0.12   1612 svchost
     55       3     1088        852    27     0.14   1220 svchost
     22       2      504        712    23     0.14    772 winampa
    120       4     2364       1228    35     0.26   1876 svchost
    170       5     4516        796    44     0.27   1260 GoogleToolbarNotifier
    193       5     2916       1488    59     0.29   1040 svchost
     64       3      812       1080    29     0.30   1252 ctfmon
    140       5     3208       1220    41     0.32   1524 spoolsv
    281      14     1764       1688    37     0.34   1120 svchost
     57       3     1028        996    30     0.39    932 atiptaxx
    503      52     7296       3596    51     2.47    836 winlogon
    259       6     1432       1340    19     2.48    880 services
    341       8     3572       1856    40     5.36    892 lsass
    240     158    29536      10388   175     5.58   1780 outpost
    149       4     2940       1108    41     9.29   1248 kav
    398       5    36140      26408   137     9.97   1984 powershell
    375      12    15020      10456    75    14.03   1116 explorer
    376       0        0         36     2    14.97      4 System
    409       6     2500       3192    26    20.10    812 csrss
   1513      54    13528       9800    95    25.78   1156 svchost
    717      75    37432        704   145    56.97   1748 kavsvc
    152       4     2372       2716    38    58.09   2028 wmiprvse
    307      13    10952      27080   173  9128.03   1200 WINWORD

Для сортировки в обратном порядке используется параметр Descending:

PS C:\> Get-Process | Sort-Object cpu -Descending

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    307      13    10956      27040   173  9152.23   1200 WINWORD
    152       4     2372       2716    38    59.19   2028 wmiprvse
    717      75    37432       1220   145    57.15   1748 kavsvc
   1524      54    13528       9800    95    26.13   1156 svchost
    410       6     2508       3224    26    20.62    812 csrss
    376       0        0         36     2    15.11      4 System
    377      13    15020      10464    75    14.20   1116 explorer
    374       5    36484      26828   137    10.53   1984 powershell
    149       4     2940       1108    41     9.34   1248 kav
    240     158    29536      10388   175     5.61   1780 outpost
    344       8     3572       1856    40     5.40    892 lsass
    512      53     7324       3608    51     2.51    836 winlogon
    259       6     1432       1340    19     2.48    880 services
     57       3     1028        996    30     0.39    932 atiptaxx
    281      14     1764       1688    37     0.34   1120 svchost
    140       5     3208       1220    41     0.32   1524 spoolsv
     64       3      812       1080    29     0.30   1252 ctfmon
    193       5     2916       1488    59     0.29   1040 svchost
    170       5     4516        796    44     0.27   1260 GoogleToolbarNotifier
    120       4     2364       1228    35     0.26   1876 svchost
     22       2      504        712    23     0.15    772 winampa
     55       3     1088        852    27     0.14   1220 svchost
     39       1      364        464    17     0.13   1644 ati2evxx
    163       6     1536       1404    35     0.12   1612 svchost
     30       2      672        724    27     0.11   1700 WinCinemaMgr
     21       1      164         60     4     0.09    748 smss
     98       5     1104        764    32     0.09    252 alg
     36       2      728         32    23     0.05   1792 klswd
      0       0        0         16     0               0 Idle

В рассмотренных нами примерах конвейеры состояли из двух командлетов. Это не обязательное условие, конвейер может объединять и большее количество команд, например:

Get-Process | Where-Object {$_.Id -gt 1000} | Sort-Object cpu -Descending

Управление выводом команд в PowerShell

Работая в оболочке PowerShell, мы пока не задумывались, каким образом система формирует строки текста, которые выводятся на экран в результате выполнения той или иной команды (напомним, что командлеты PowerShell возвращают .NET-объекты, которые, как правило, не знают, каким образом отображать себя на экране).

На самом деле в PowerShell имеется база данных (набор XML-файлов), содержащая модули форматирования по умолчанию для различных типов .NET-объектов. Эти модули определяют, какие свойства объекта отображаются при выводе и в каком формате: списка или таблицы. Когда объект достигает конца конвейера, PowerShell определяет его тип и ищет его в списке объектов, для которых определено правило форматирования. Если данный тип в списке обнаружен, то к объекту применяется соответствующий модуль форматирования; если нет, то PowerShell просто отображает свойства этого .NET-объекта.

Также в PowerShell можно явно задавать правила форматирования данных, выводимых командлетами, и подобно командному интерпретатору Cmd.exe перенаправлять эти данные в файл, на принтер или в пустое устройство.

Форматирование выводимой информации

В традиционных оболочках команды и утилиты сами форматируют выводимые данные. Некоторые команды (например, dir в интерпретаторе Cmd.exe) позволяют настраивать формат вывода с помощью специальных параметров.

В оболочке PowerShell вывод форматируют только четыре специальных командлета Format (табл. 17.3). Это упрощает изучение, так как не нужно запоминать средства и параметры форматирования для других команд (остальные командлеты вывод не форматируют).

Командлеты PowerShell для форматирования вывода
Командлет Описание
Format-Table Форматирует вывод команды в виде таблицы, столбцы которой содержат свойства объекта (также могут быть добавлены вычисляемые столбцы). Поддерживается возможность группировки выводимых данных
Format-List Вывод форматируется как список свойств, в котором каждое свойство отображается на новой строке. Поддерживается возможность группировки выводимых данных
Format-Custom Для форматирования вывода используется пользовательское представление (view)
Format-Wide Форматирует объекты в виде широкой таблицы, в которой отображается только одно свойство каждого объекта

Как уже отмечалось выше, если ни один из командлетов Format явно не указан, то используется модуль форматирования по умолчанию, который определяется по типу отображаемых данных. Например, при выполнении командлета Get-Service данные по умолчанию выводятся как таблица с тремя столбцами (Status, Name и DisplayName):

PS C:\> Get-Service

Status   Name               DisplayName
------   ----               -----------
Stopped  Alerter            Оповещатель
Running  ALG                Служба шлюза уровня приложения
Stopped  AppMgmt            Управление приложениями
Stopped  aspnet_state       ASP.NET State Service
Running  Ati HotKey Poller  Ati HotKey Poller
Running  AudioSrv           Windows Audio
Running  BITS               Фоновая интеллектуальная служба пер...
Running  Browser            Обозреватель компьютеров
Stopped  cisvc              Служба индексирования
Stopped  ClipSrv            Сервер папки обмена
Stopped  clr_optimizatio... .NET Runtime Optimization Service v...
Stopped  COMSysApp          Системное приложение COM+
Running  CryptSvc           Службы криптографии
Running  DcomLaunch         Запуск серверных процессов DCOM
Running  Dhcp               DHCP-клиент
...

Для изменения формата выводимых данных нужно направить их по конвейеру соответствующему командлету Format. Например, следующая команда выведет список служб с помощью командлета Format-List:

PS C:\> Get-Service | Format-List

Name                : Alerter
DisplayName         : Оповещатель
Status              : Stopped
DependentServices   : {}
ServicesDependedOn  : {LanmanWorkstation}
CanPauseAndContinue : False
CanShutdown         : False
CanStop             : False
ServiceType         : Win32ShareProcess

Name                : ALG
DisplayName         : Служба шлюза уровня приложения
Status              : Running
DependentServices   : {}
ServicesDependedOn  : {}
CanPauseAndContinue : False
CanShutdown         : False
CanStop             : True
ServiceType         : Win32OwnProcess
. . .

Как мы видим, при использовании формата списка выводится больше сведений о каждой службе, чем в формате таблицы (вместо трех столбцов данных о каждой службе в формате списка выводятся девять строк данных). Однако это вовсе не означает, что командлет Format-List извлекает дополнительные сведения о службах. Эти данные содержатся в объектах, возвращаемых командлетом Get-Service, однако командлет Format-Table, используемый по умолчанию, отбрасывает их, потому что не может вывести на экран более трех столбцов.

При форматировании вывода с помощью командлетов Format-List и Format-Table можно указывать имена свойства объекта, которые должны быть отображены (напомним, что просмотреть список свойств, имеющихся у объекта, позволяет рассмотренный ранее командлет Get-Member ). Например:

PS C:\> Get-Service | Format-List Name, Status, CanStop

Name    : Alerter
Status  : Stopped
CanStop : False

Name    : ALG
Status  : Running
CanStop : True

Name    : AppMgmt
Status  : Stopped
CanStop : False
. . .

Вывести все имеющиеся у объектов свойства можно с помощью параметра *, например:

PS C:\> Get-Service | Format-table *

Перенаправление выводимой информации

В оболочке PowerShell имеются несколько командлетов, с помощью которых можно управлять выводом данных. Эти командлеты начинаются со слова Out, их список можно увидеть следующим образом:

PS C:\> Get-Command out-* | Format-Table Name

Name
----
Out-Default
Out-File
Out-Host
Out-Null
Out-Printer
Out-String

По умолчанию выводимая информация передается командлету Out-Default, который, в свою очередь, делегирует всю работу по выводу строк на экран командлету Out-Host. Для понимания данного механизма нужно учитывать, что архитектура PowerShell подразумевает различие между собственно ядром оболочки (интерпретатором команд) и главным приложением (host), которое использует это ядро. В принципе, в качестве главного может выступать любое приложение, в котором реализован ряд специальных интерфейсов, позволяющих корректно интерпретировать получаемую от PowerShell информацию. В нашем случае главным приложением является консольное окно, в котором мы работаем с оболочкой, и командлет Out-Host передает выводимую информацию в это консольное окно.

Параметр Paging командлета Out-Host, подобно команде more интерпретатора Cmd.exe, позволяет организовать постраничный вывод информации, например:

Get-Help Get-Process –Full | Out-Host -Paging

Сохранение данных в файл

Командлет Out-File позволяет направить выводимые данные вместо окна консоли в текстовый файл. Аналогичную задачу решает оператор перенаправления (>), однако командлет Out-File имеет несколько дополнительных параметров, с помощью которых можно более гибко управлять выводом: задавать тип кодировки файла (параметр Encoding ), задавать длину выводимых строк в знаках (параметр Width ), выбирать режим перезаписи файла (параметры Append, noClobber ). Например, следующая команда направит информацию о зарегистрированных на компьютере службах в файл C:\service.txt, причем данный файл будет записан в формате ASCII:

Get-Process | Out-File -FilePath C:\Process.txt -Encoding ASCII

Печать данных

Данные можно вывести непосредственно на принтер с помощью командлета Out-Printer. При этом печать может производиться как на принтере по умолчанию (никаких специальных параметров для этого указывать не нужно), так и на произвольном принтере (в этом случае отображаемое имя принтера должно быть указано в качестве значения параметра Name ). Например:

PS C:\script> Get-Process | Out-Printer -Name "Xerox Phaser 3500 PCL 6"

Подавление вывода

Командлет Out-Null служит для отбрасывания любых своих входных данных. Это может пригодиться для подавления вывода на экран ненужных сведений, полученных в качестве побочного эффекта выполнения какой-либо команды. Например, при создании каталога командой mkdir на экран выводится его содержимое:

PS C:\> mkdir klop

    Каталог: Microsoft.PowerShell.Core\FileSystem::C:\


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        03.12.2007      1:01            klop

Если вы не желаете видеть эту информацию, то результат выполнения команды mkdir нужно передать по конвейеру командлету Out-Null:

mkdir klop | Out-Null
Вернуться к учебному плану