Главная > Powershell > Подводные камни Powershell

Подводные камни Powershell

Прочёл на досуге занимательную книжечку под названием The Big Book of PowerShell Gotchas, что можно перевести как “Большая книга по подводным камням Powershell”. Книга бесплатная, более того авторы призывают ею делиться с ближним со всеми желающими, только просят не изменять оригинал. Эту и многие другие книги можно скачать с сайта powershell.org, а точнее из каталога в SkyOneDrive.

Сразу скажу, что книга эта не для начинающих – подразумевается, что человек, читающий её, уже знаком с синтаксисом, и имеет какой-то опыт работы с Powershell. Читается легко, картинок больше, чем текста 🙂 Под картинками я имею в виду скриншоты. Вообще по сути вся книга это скриншоты консоли с командами, и результатами их выполнения. А в тексте лишь объясняется почему результат получился именно таким (а не таким, как часто ожидалось).

Кому-то всё будет понятным и очевидным, кому-то не очень. В любом случае всем рекомендую к прочтению.

Я же поделюсь парой, как мне показалось, интересных моментов.

Допустим, мы делаем инвентаризацию компьютера, собираем информацию о жёстких дисках:

Get-WmiObject Win32_LogicalDisk -Filter "DriveType=3" | Select-Object `
  @{name='Name'; expression={$_.Name}},
  @{name='FreeSpace(GB)'; expression={$_.FreeSpace / 1GB -as [int]}},
  @{name='Size (GB)'; expression={$_.Size / 1GB -as [int]}},
  @{name='FreePersent'; expression={$_.FreeSpace / $_.Size * 100 -as [int]}} |
  Format-Table -AutoSize

Получаем некий результат:

Name FreeSpace(GB) Size (GB) FreePersent
---- ------------- --------- -----------
C:              12        30          39
D:               5        75           6
E:              25        30          82
F:              32        51          62
K:               8       200           4
L:             216       236          92

Отлично!

Теперь этот результат мы хотим сохранить в html-файл:

Get-WmiObject Win32_LogicalDisk -Filter "DriveType=3" | Select-Object `
  @{name='Name'; expression={$_.Name}},
  @{name='FreeSpace(GB)'; expression={$_.FreeSpace / 1GB -as [int]}},
  @{name='Size (GB)'; expression={$_.Size / 1GB -as [int]}},
  @{name='FreePersent'; expression={$_.FreeSpace / $_.Size * 100 -as [int]}} |
  Format-Table -AutoSize | ConvertTo-Html | Out-File c:\diskreport.html

Но результат получаем совсем не такой как ожидали:

Html Table

Почему так происходит?

Дело в том, что командлеты форматирования (в данном случае Format-Table) добавляют в выводимую информацию специальный код, предназначенный исключительно для отображения информации на экране.

Чтобы этого не происходило нужно запомнить одно простое правило: после командлетов форматирования не должно быть других командлетов. Т.е. командлет форматирования должен быть последним в строке. После командлетов форматирования могут идти только выводящие командлеты: Out-Host, Out-File и т.д.

Какой выход из этой ситуации? – Просто убрать Format-Table:

Get-WmiObject Win32_LogicalDisk -Filter "DriveType=3" | Select-Object `
  @{name='Name'; expression={$_.Name}},
  @{name='FreeSpace(GB)'; expression={$_.FreeSpace / 1GB -as [int]}},
  @{name='Size (GB)'; expression={$_.Size / 1GB -as [int]}},
  @{name='FreePersent'; expression={$_.FreeSpace / $_.Size * 100 -as [int]}} |
  ConvertTo-Html | Out-File c:\diskreport.html

В в результате получим:

Html Table (format)

Ещё одна в чём-то похожая особенность.

Допустим, мы хотим получить какую-то информацию по работающим службам (для наглядности каждая часть команды, содержащая по одному командлету идёт с новой строки):

Get-Service |
Select-Object Name, DisplayName |
Where-Object {$_.Status -eq 'Running'} |
Sort-Object Name

Такая команда нам ничего не покажет. Почему?

Я обычно строю команды слева направо: сначала получаю данные, смотрю, что получилось, потом постепенно выбираю из них нужную информацию, опять смотрю, и только потом форматирую результат.

Для тех, кто любит сразу нафигачить длиннющую команду, а потом разбираться почему она не работает (или при разборе чужих команд), хорошим способом для понимания, что пошло не так может послужить вариант разбирать свою команду справа налево: сокращать команду отбрасывая справа командлеты до тех пор, пока не появится какой-то результат. И эту рабочую команду “скормить” командлету Get-Member.

Как это выглядит на практике…

Мы уже выяснили, что команда выше нам ничего не покажет. Отбрасываем последний командлет и смотрим, что получится:

Get-Service |
Select-Object Name, DisplayName |
Where-Object {$_.Status -eq 'Running'}

Опять ничего.

Отбрасываем ещё один командлет:

Get-Service |
Select-Object Name, DisplayName

А вот здесь уже появляется результат. (Я не буду приводить скриншот – очевидно, что результатом будет список из имени службы и отображаемого имени.) Теперь, чтобы понять, что мы имеем, и что можем с этим делать засовываем нашу команду в Get-Member:

Get-Service |
Select-Object Name, DisplayName |
Get-Member

Получаем следующее:

   TypeName: Selected.System.ServiceProcess.ServiceController

Name        MemberType   Definition                                          
----        ----------   ----------                                          
Equals      Method       bool Equals(System.Object obj)                      
GetHashCode Method       int GetHashCode()                                   
GetType     Method       type GetType()                                      
ToString    Method       string ToString()                                   
DisplayName NoteProperty System.String DisplayName=Adobe LM Service
Name        NoteProperty System.String Name=Adobe LM Service

Как видно из результата здесь нет свойства status, и следовательно конструкции

Where-Object {$_.Status -eq 'Running'}

нечего обрабатывать. Поэтому на выходе мы ничего не получим.

В завершение хочется ещё раз сказать, что это лишь пара примеров из одной книги. А эта книга лишь одна из представленных на сайте. Я думаю, что независимо от опыта, умения и знания в Powershell, каждый найдёт для себя интересующую книгу.

Развиваемся, коллеги 🙂

Реклама
Рубрики:Powershell Метки:
  1. Комментариев нет.
  1. No trackbacks yet.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: