Глава 7. Добавление команд

Одной из самых сильных сторон PowerShell является его расширяемость. Поскольку Microsoft продолжает вкладываться в PowerShell, они разрабатывают всё больше и больше команд для промышленного применения, например для Azure compute (Virtual Machines), Azure SQL, Azure Virtual Network, Azure DNS и тому подобного. Обычно вы управляете ими через сам портал Azure. Позднее в этой главе мы обсудим как устанавливать модули Azure PowerShell.

Как одна оболочка может делать всё

Как одна оболочка способна выполнять всё? Давайте представим себе ваш смартфон. Как вы можете добавлять в свой телефон функциональные возможности без обновления его операционной системы? Вы устанавливаете некое прикладное приложение (app).

Когда вы устанавливаете некое прикладное приложение, оно способно добавлять устройства (widgets) или даже добавлять команды, которые вы можете произносить своему голосовому помощнику. Добавление команд вашему голосовому помощнику, вероятно, наиболее схоже с расширением модели PowerShell. PowerShell предоставляет способы добавления команд, которые вы можете применять.

Итак, допустим, вы установили некое прикладное приложение с названием Ride Share. Данное прикладное приложение добавляет голосовые команды, которые позволяют вам произнести "Закажи мне поездку с Ride Share". Ваш телефон отыщет адрес вашей работы и отправит необходимую команду в соответствующее прикладное приложение.

PowerShell работает аналогично. PowerShell именует свои расширения модулями. Нет никаких устройств, однако команды можно добавлять. Мы обсудим позднее в своём следующем разделе то, как устанавливать модули.

Расширения: поиск и установка модулей

Вплоть до PowerShell 6.0 имелось два вида расширений: модули и оснастки (modules и snap-ins). PowerShell v6 и более новые поддерживают один тип расширений с названием модуль. Модули разрабатываются так, чтобы быть более самодостаточными и более простыми для распространения.

Microsoft представила модуль с названием PowerShellGet, который упрощает поиск, выгрузку, установку и обновление модулей из Интернет репозиториев. PowerShellGet во многом схож с любимыми администраторами Linux диспетчерами пакетов - pm, yum, apt-get и тому подобными. Microsoft даже запустила Интернет галерею, или репозиторий, с названием PowerShell Gallery.

[Предостережение]Предостережение

Microsoft запустила не означает Microsoft производит, проверяет и одобряет. Галерея PowerShell содержит распространяемый сообществом код и вам надлежит предпринимать меры предосторожности перед исполнением чьего- то ещё кода в своей среде.

Как и в большинстве поисковых механизмов, вы можете выполнять поиск модулей в PowerShell Gallery. Модули для Azure носят название Az. Рисунок 7.1 отображает образец поиска такого модуля.

 

Рисунок 7-1


Отображение поиска Az в Галерее PowerShell

Если вы кликните по названию модуля Az, это предъявит дополнительные сведения о данном модуле. Под Package Details > PSEditions вы можете убедиться проверяли ли его вторы данный модуль в PowerShell Core (Рисунок 7.2).

 

Рисунок 7-2


Отображение поиска факта, что этот модуль Core совместим

Затем взгляните на Installation Options (Рисунок 7.3).

 

Рисунок 7-3


Отображение доступных через Галерею PowerShell команд установки

Обратите внимание на то, что для работы данного модуля требуется по крайней мере PowerShell 5.1, а также здесь предоставляются инструкции по тому как устанавливать данный модуль. Когда мы выполним команду Install-Module -Name Az, мы сможем пронаблюдать что происходит:


PS C:\Scripts> Install-Module az 
 
Untrusted repository
You are installing the modules from an untrusted repository. If you trust this 
repository, change its InstallationPolicy value by running the Set-PSRepository
 cmdlet. Are you sure you want to install the modules from 'PSGallery'?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help 
(default is "N"):y
		

Она выдаёт вам запрос на подтверждение, спрашивая у вас доверяете ли вы установке из данной Галереи и, если вы скажете да, тогда она установит этот модуль. Вы можете запустить команду Get-Module для проверки установки данного модуля, однако, по той причине, что этот модуль не загружен, требуется параметр -ListAvailable :


PS C:\Scripts> Get-Module az -ListAvailable
 
    Directory: 
    C:\Users\Tyler\Documents\powershell\Modules
 
ModuleType Version    Name
---------- -------    ----                               
Script     6.3.0      Az
		

У вас могут отличаться значения пути и версии, но сам вывод должен быть аналогичным.

[Замечание]Дополнительно о получении модулей из Интернета

Модуль PowerShellGet позволяет устанавливать модули из PowerShell Gallery. Применение PowerShellGet простое и даже может быть занимательным:

  • Для добавления URL из репозитория запустите Register-PSRepository. PowerShell Gallery обычно установлен по умолчанию Code, но можно даже настроить свою собственную "Галерею" внутри частного применения и вам надлежит воспользоваться Register-PSRepository для указания на неё.

  • Для поиска модулей в репозитории воспользуйтесь Find-Module. Вы можете применять символы подстановки * в названиях, определить теги, а также обладаете большим выбором для выравнивания своих результатов поиска.

  • Для выгрузки и установки модуля после его нахождения примените Install-Module.

  • Чтобы убедиться что ваша локальная копия модуля обладает самой последней версией, используйте Update-Module и, если это не так, выгрузите и установите самую последнюю.

PowerShellGet содержит ряд прочих команд (PowerShell Gallery предоставляет ссылку на необходимую документацию), однако вы начнёте пользоваться именно этими. Например, попробуйте установить из Галереи PowerShell модуль Azure PowerShell или PSScriptTools Джефа Хикса.

Расширения: поиск и добавление модулей

PowerShell автоматически выполняет поиск по определённому набору путей для нахождения модулей. Переменная окружения PSModulePath определяет значение путей, в которых PowerShell ожидает пребывание модулей:


PS /Users/Tyler> (Get-Content Env:/PSModulePath) -split ':'
C/Users/Tyler.local/share/powershell/Modules
/usr/local/share/powershell/Modules
/usr/local/microsoft/powershell/7/Modules 
		
[Совет]Попробуйте прямо сейчас

Наша предыдущая команда была исполнена в устройстве macOS. Запустите команду (Get-Content Env:/PSModulePath) -split ':' и посмотрите какие результаты у вас. Обратите внимание, что они будут отличаться в зависимости от используемой вами ОС.

Как вы можете видеть в данном примере, имеются три определённых по умолчанию местоположения: одно в той папке, в которой установлен PowerShell, где обитают модули системы; одно в папке local/share/, в которую вы можете помещать модули, совместно применяемые всеми пользователями; и одно в папке .local, в которую вы можете помещать любые персональные модули. Если вы запускаете ещё более позднюю версию PowerShell, вы можете обнаружить дополнительные местоположения, которыми теперь пользуется Microsoft. Мы также способны добавлять модули из любых прочих местоположений, предоставляя известные вам полные пути. В своей машине Windows вы обнаружите аналогичную схему, в которой установлены модули:


$env:PSModulePath -split ';'
 
C:\Users\Administrator\Documents\PowerShell\7\Modules
C:\Program Files\WindowsPowerShell\Modules
C:\Windows\system32\PowerShell\7\Modules
		

В PowerShell важно значение пути. Когда у вас имеются модули, располагаемые где- то ещё, вы обязаны добавлять пути к ним в своей переменной PSModulePath. Вы можете осуществить это в своём профиле при помощи приводимой ниже команды (позднее в данной главе мы рассмотрим настройку профиля):


S C:\Scripts> $env:PSModulePath += [System.IO.Path]::PathSeparator + 
➥ 'C:\Scripts/myModules' 
		
[Замечание]Замечание

Обратите внимание, что имеется ряд моментов, о которых мы не упоминали в своём предыдущем примере. Но это нормально, мы обещаем вернуться к ним.

Почему значение PSModulePath настолько важно? По той причине, что при его помощи PowerShell способен автоматически устанавливать местоположение всех имеющихся в вашем компьютере модулей. После того как он отыщет ваши модули, PowerShell автоматически обнаружит их. Для вас это будет выглядеть так, как будто все модули в вашей машине загружены всё время. Запросите подсказку для некоторого модуля и вы получите её, причём без без необходимости его загрузки. Выполните найденную вами команду и PowerShell автоматически загрузит необходимый модуль, содержащий данную команду. Команда PowerShell Update-Help также пользуется PSModulePath для выявления того какие именно модули у вас имеются, а затем отыскивает обновления файлов подсказок для каждого из них.

Скажем, для удаления любых загруженных модулей выполните Get-Module | Remove-Module . Это удалит почти все команды из вашего текущего сеанса, а потому, раз вы испробовали это, закройте и повторно откройте PowerShell. Затем исполните такую команду (ваши результаты могут слегка отличаться, в зависимости от вашей ОС и того какие модули установлены):


PS C:\Scripts> help *storaget*
       Name                                    Category ModuleName
 
       Get-AzStorageTable                      Cmdlet   Az.Storage
       Get-AzStorageTableStoredAccessPolicy    Cmdlet   Az.Storage
       New-AzStorageTable                      Cmdlet   Az.Storage
       New-AzStorageTableSASToken              Cmdlet   Az.Storage
       New-AzStorageTableStoredAccessPolicy    Cmdlet   Az.Storage
       Remove-AzStorageTable                   Cmdlet   Az.Storage
       Remove-AzStorageTableStoredAccessPolicy Cmdlet   Az.Storage
       Set-AzStorageTableStoredAccessPolicy    Cmdlet   Az.Storage 
		

Как вы можете видеть, PowerShell выявляет определённые команды (либо разновидность Cmdlet), которые обладают в своём названии словом storage (я пользуюсь storaget для упрощения результатов в данном примере). Вы можете затем запросить подсказку по одному из них, даже хотя вы и не загружали его модуль:


PS C:\Scripts> Get-Help Get-AzStorageTable           
       NAME
       Get-AzStorageTable
SYNOPSIS
    Lists the storage tables.
 
SYNTAX
    Get-AzStorageTable [[-Name] <System.String>] [-Context
<Microsoft.Azure.Commands.Common.Authentication.Abstractions.IStorageContext>]
➥ [-DefaultProfile
 
<Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core
➥ .IAzureContextContainer>] [<CommonParameters]
		

Если вы пожелаете, вы даже можете запустить такую команду, и PowerShell убедится что данный модуль загружен для вас. Такие автообнаружение и автозагрузка полезны функционально, помогают вам отыскивать и применять команды, которые не присутствуют в вашей оболочке при её запуске.

Автообнаружение модулей PowerShell делает возможным для оболочки заполнять названия команд (при помощи Tab в вашей консоли, либо IntelliSense в установленном Visual Studio Code), отображать подсказку и запускать команды, даже когда модули не были загружены в явном виде в оперативную память. Такие функциональные возможности оправдывают ваши усилия по поддержке PSModulePath как можно более компактным (то есть не размещайте в ней много различных местоположений) и поддержке ваших модулей в актуальном состоянии.

Но что если некий модуль не расположен в одном из тех путей, на которые ссылается PSModulePath? Вам необходимо исполнить Import-Module и определить полный путь к такому модулю, например, C:\Scripts/myModules/myModule.

Модули также способны добавлять поставщиков PowerShell. Запуск Get-PSProvider снабдит вас перечнем поставщиков:


PS /Users/James> get-psprovider
 
Name                 Capabilities                  Drives
----                 ------------                  ------
Alias                ShouldProcess                 {Alias}
Environment          ShouldProcess                 {Env}
FileSystem           Filter, ShouldProcess, Crede... {/, Temp}
Function             ShouldProcess                 {Function}
Variable             ShouldProcess                 {Variable}
		
[Замечание]Установка команд Google Cloud

Установка и добавление команд Google Cloud слегка отличается по той причине, что они нарушают правило - они требуют ввода при первом применении вами соответствующего модуля. Вы устанавливаете их команды впервые просто как прочие модули: Install-Module -Name Google-Cloud. Однако, если вы попробуете найти эти команды, это завершится отказом. Поэтому вам необходимо выполнить Import-Module GoogleCloud -Force. Параметр -Force применяется в том случае, когда PowerShell считает что соответствующий модуль загружен, он попытается перезагрузить его. Теперь такой модуль выдаст вам приглашение для завершения его установки (при условии, что он всё ещё спроектирован так, как на момент написания этих строк). Теперь мы запустим команды для работы с экземплярами Google Cloud SQL.


PS C:\Scripts> Get-Command -Name *-gcSqlinstance 
 
CommandType     Name
-----------     ----                                             
Cmdlet          Add-GcSqlInstance                                
Cmdlet          ConvertTo-GcSqlInstance                          
Cmdlet          Export-GcSqlInstance                             
Cmdlet          Get-GcSqlInstance                                
Cmdlet          Import-GcSqlInstance                             
Cmdlet          Remove-GcSqlInstance                             
Cmdlet          Restart-GcSqlInstance                            
Cmdlet          Update-GcSqlInstance
		

Конфликты команд и удаление расширений

Давайте ближе взглянем на добавленные нами команды как для экземпляров Google Cloud SQL, так и для хранилищ Azure Table. Заметили нечто особенное в названиях этих команд?

Большинство расширений PowerShell, за исключением Amazon Web Services, добавляют короткий префикс в соответствующей части существительного в своих названиях команд. Например, Get-GcSqlInstance или Get-AzStorageTable. Такие префиксы могут казаться неудобными, но они предназначены для предотвращения конфликтов команд.

Скажем, предположим вы загрузили два модуля, каждый из которых содержит командлет Get-User. При двух обладающих одинаковым названием командах, которые ещё и загружены одновременно, какую именно исполнит PowerShell когда вы запустите Get-User? Как оказывается, последнюю загруженную. Но другая команда с таким же точно названием не является недоступной. Чтобы определённо запускать какую- то из команд, вам надлежит применять несколько неудобное соглашение о именовании, требующее как названия самого модуля, так и название необходимой команды. Когда одна из команд Get-User поступает из модуля MyCoolPowerShellModule, вам придётся пользоваться следующим:


MyCoolPowerShellModule\Get-User
 	   

Это приводит к чрезмерному набору и именно по этой причине Microsoft предлагает добавлять специфичный для продукта префикс, например Az или Gc к соответствующему существительному каждой из команд. Добавление префикса способствует предотвращению конфликтов и помогает более простым идентификации и применению команд.

[Замечание]Замечание

Модуль Amazon Web Services не пользуется префиксами.

Если вы столкнулись с неким конфликтом, вы всегда можете удалить один из конфликтующих модулей. Запустите Remove-Module совместно с названием модуля для выгрузки модуля.

[Замечание]Замечание

При импорте соответствующего модуля добавляйте свой собственный префикс к любому модулю. Import-Module ModuleName -Prefix MyPrefix изменит Get-OriginalCmdLet на Get-MyPrefixOriginalCommand.

Воспроизведение новыми модулями

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

Наша цель состоит в сжатии файла в нашем компьютере в некий архив zip. У нас даже нет никаких соображений способен ли PowerShell выполнять это, поэтому начнём с запроса системной подсказки для какого- то ключа:


PS C:\Scripts> help *-archive                            
Name                              Category  Module                     
----                              --------  ------                     
Compress-Archive                  Function  Microsoft.PowerShell.Arc... 
		

Ага! Как мы можем видеть, у нас в компьютере имеется целый модуль Microsoft.PowerShell.Archive (его полное название было усечено). Наш предыдущий список показывает команду Compress-Archive, но нам любопытно какие ещё команды доступны. Для поиска мы вручную загружаем этот модуль и перечисляем его команды:


PS C:\Scripts> get-command -Module Microsoft.PowerShell.Archive
 
 
CommandType     Name
-----------     ----                                              
Function        Compress-Archive                                  
Function        Expand-Archive
		
[Замечание]Замечание

У нас имеется возможность запроса подсказки в Compress-Archive или даже в запуске соответствующей команды непосредственно. PowerShell придётся загрузить нам этот модуль Microsoft.PowerShell.Archive в фоновом режиме. Однако поскольку мы обучаемся, такой подход позволит нам просмотреть полный список команд этого модуля.

Такой список команд выглядит более или менее похожим на все более ранние списки. Отлично, давайте посмотрим как выглядит наша команд Compress-Archive:


PS C:\Scripts> Get-Help Compress-Archive
 
NAME
    Compress-Archive
    
SYNTAX
    Compress-Archive [-Path] <string[]> [-DestinationPath] 
    <string> [-CompressionLevel {Optimal | NoCompression | 
    Fastest}] [-PassThru] [-WhatIf] [-Confirm] 
    [<CommonParameters>]
		

Выглядит просто и лишь -Path и -DestinationPath выступают обязательными параметрами. Давайте создадим некий файл и сожмём его при помощи данной команды:


PS C:\Scripts> 'test lunch' | Out-File chapter7.txt                     
PS C:\Scripts> Compress-Archive -Path .\chapter7.txt -DestinationPath 
➥ .\chapter7.zip 
		

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


PS C:\Scripts> Compress-Archive -Path .\chapter7.txt -DestinationPath .\chapter7.zip -Force -Verbose                   
VERBOSE: Preparing to compress...
VERBOSE: Performing the operation "Compress-Archive" on target 
➥ "C:\Scripts\chapter7.txt".
VERBOSE: Adding 'C:\Scripts/chapter7.txt'.
		

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

Общие моменты путаницы

Когда новички PowerShell приступают к работе с модулями, они зачастую неверно выполняют одно дело: они не знакомятся с имеющейся подсказкой. В частности, они не пользуются переключателями -Example или -Full при запросе подсказки.

Честно говоря, просмотр встроенных образцов это наилучший способ обучению применения команды. Да, прокручивание перечня из сотен команд может быть слегка сложным (к примеру, модули Az.* добавляют 00 новых команд), однако применение Help и Get-Command с символами подстановки должно облегчить список для любого существительного, которое по вашему мнению необходимо вам. Следовательно, читайте соответствующую подсказку!

Лабораторные занятия

Как и обычно, мы предполагаем что у вас имеется самая последняя версия PowerShell в компьютере или виртуальной машине для проведения тестирования:

  1. Просмотрите PowerShell Gallery. Найдите модуль или даже пару, которые, как вы полагаете, звучат интересными и установите их.

  2. Просмотрите доступные для этого только что выгруженного модуля команды.

  3. Воспользуйтесь командами из Раздела 7.2 и установите (если это необходимо) самую последнюю версию модуля Microsoft для работы с архивами, который содержит команду Compress-Archive.

  4. Импортируйте только что установленный модуль.

  5. Создайте для своего следующего шага папку Tests с 10 файлами в ней и озаглавьте её ~/TestFolder.

  6. Воспользуйтесь Compress-Archive для создания некого zip содержимого ~/TestFolder и назовите полученный архив TestFolder.zip

  7. Раскройте полученный архив в ~/TestFolder2.

  8. Для сравнения только названий имеющихся файлов в соответствующих папках воспользуйтесь Compare-Object и Select-Object -ExpandProperty Name чтобы проверить что у вас имеются те же самые файлы.

Ответы лабораторных занятий

Вот один из подходов к этому:

  1. Install-Module moduleyoufound

    Если вы в машине Windows, мы ожидаем модуль import-excel.

  2. Get-Command –module moduleyoufound

    - Get-command -module az

  3. Find-Module -Command Compress-Archive | Install-Module -Force

  4. Import-Module Microsoft.PowerShell.Archive

  5. 1..10 создаст набор чисел от 1 до 10. Если вы сделали это иначе, ничего страшного.

    - New-Item ~/TestFolder -ItemType Directory

    - 1..10 | ForEach-Object {New-Item "~/TestFolder/$_.txt" -ItemType File -Value $_}

  6. Compress-Archive ~/TestFolder/* -DestinationPath ~/TestFolder.zip

  7. Expand-Archive ~/TestFolder.zip -DestinationPath ~/TestFolder2

  8. Это некий возможный вариант. Помните, dir это псевдоним для Get-ChildItem.

    $reference = Get-ChildItem ~/TestFolder| Select-Object -ExpandProperty name

    $difference = Get-ChildItem ~/TestFolder3| Select-Object -ExpandProperty name

    Compare-Object -ReferenceObject $reference -DifferenceObject $difference