Использование областей переменных в PowerShell

PowerShell

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

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

Что такое области PowerShell?

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

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

Области имеют иерархическую структуру: глобальная область считается родительской. Переменные, определенные в глобальной области, автоматически доступны для просмотра в дочерней области. В то же время, переменные, определенные в дочерней области, недоступны для родительской области.

В отношении областей PowerShell действуют следующие основные правила:

  • Области “вложены” друг в друга. Внешняя область является родительской, а все вложенные области являются для нее дочерними.
  • Любой элемент доступен в области, в которой он определен, а также во всех ее дочерних областях (если он не определен как частный).
  • Созданный в области элемент можно изменить только в той области, в которой он был определен. Другой элемент с тем же именем в другой области может скрывать исходный элемент, но не отменяет и не изменяет его.

Глобальная область и область сценария

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

Этот сценарий определяет переменную $greeting в области сценария (или локальной области). Однако эта переменная и ее значение не будут доступны в консоли PowerShell, которая является родительской областью. Ниже представлены результаты команд PowerShell:

Отобразим текущее значение переменной $greeting в консоли (или глобальной области) — как и предполагалось, оно пустое. Запускаем файл сценария, в котором определена и выводится на экран переменная $greeting. После выхода из сценария снова посмотрим значение $greeting в консоли PowerShell — оно по-прежнему пустое. Это вполне очевидно, поскольку переменная $greeting находится в дочерней области сценария, а не в родительской глобальной области.

Теперь рассмотрим противоположную ситуацию. Определим значение $greeting не в сценарии, а в глобальной области. В этом случае сценарий показывает значение переменной $greeting, поскольку он унаследовал переменную от глобальной области.

В самом сценарии мы не устанавливали и не изменяли переменную $greeting. Мы только отобразили ее значение. Строка приветствия унаследована от консоли как родительской области файлом сценария как дочерней областью.

Использование модификаторов области

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

 

Модификатор области Применение
global: Переменная существует в глобальной области
local: Переменная существует в локальной области
private: Переменная видна только в текущей области
script: Переменная существует в области сценария, которая является ближайшей областью файла сценария, или в глобальной области при отсутствии сценария

Например, мы можем добавить префикс $global: к переменной в сценарии, чтобы изменить значение переменной, ранее определенное в глобальной родительской области. Ниже представлены выходные данные сценария и консоли:

Мы определили $greeting в глобальной области консоли как “Hello, Jeff!”. Затем мы запустили файл сценария, который изменил значение переменной на “Hello, World!” с помощью модификатора области $global:. После запуска сценария значение $greeting было изменено в глобальной области консоли на значение в сценарии.

Использование областей в модуле PowerShell

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

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

Вот пример файла модуля PowerShell (MyModule.psm1), который содержит две функции — Get-Greeting и Set-Greeting:

Обратите внимание, что обе функции ссылаются на переменную $name. Однако поскольку мы определили переменную в отдельных функциях, она доступна только для конкретных функций. Задание переменной $name в функции Set-GreetingName не влияет на переменную $name в функции Get-Greeting. Вы можете попробовать сами, сохранив этот код в файл .psm1, импортировав его с помощью команды Import-Module и указав имя файла модуля.

Несмотря на то, что мы задали переменную $name с помощью функции Set-GreetingName, это не повлияло на переменную $name в функции Get-Greeting. Каждая переменная $name привязана к соответствующей функции. Когда мы изменяем значение переменной в одной функции, это не влияет на другую функцию.

Если мы хотим, чтобы переменная была доступна для всех функций в модуле, добавляем модификатор $script: к переменной $name, например:

Если мы повторно импортируем модуль с помощью параметра -Force, то сможем установить значение $name в одной функции и ссылаться на данную переменную в другой функции.

Обратите внимание, что при вызове функции Get-Greeting отображается сообщение по умолчанию, поскольку для переменной $script:name не установлено значение. После вызова функции Set-GreetingName функция Get-Greeting выводит другое значение в зависимости от указанного мной имени. Это объясняется тем, что обе функции теперь ссылаются на одну и ту же переменную.

Хотя это очень простой пример модуля, вы можете увидеть, насколько он может быть полезен. Мы использовали эту возможность для задания учетных данных API. Пример можно найти в репозитории на GitHub: twilio-powershell-module.

Применение областей с использованием точечной нотации

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

Однако вы можете включить область сценария или функции с помощью точечной нотации. Когда сценарий выполняется в текущей области, в ней доступны любые переменные сценария. Чтобы использовать точечную нотацию, нужно поставить точку (.) и пробел перед именем сценария. Ниже приведен файл сценария и код:

Изначально значение переменной $greeting в глобальной области консоли пустое или нулевое, при этом значение $greeting устанавливается в файле scopetest.ps1. Используя точечную нотацию, сценарий переносит значение переменной в родительскую область. Вы также можете использовать оператор вызова/амперсанд (&) для запуска сценария или функции, и соответствующая область не будет добавлена в текущую область.

Дополнительные ресурсы

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

Дополнительные сведения о написании сценариев PowerShell смотрите в Руководстве по сценариям Windows PowerShell для начинающих Джеффа Петтера.

 

Бесплатный аудит рисков кибербезопасности

Узнайте об уязвимостях вашей ИТ-инфраструктуры - мы проведем бесплатный аудит рисков и подготовим для вас отчет. Это займет около 90 минут вашего времени и никак не отразится на бизнес-процессах компании.