Как стать автором
Обновить

Книга «PowerShell для сисадминов»

Блог компании Издательский дом «Питер»Системное администрированиеPowerShellПрофессиональная литература
image Привет, Хаброжители! PowerShell — это одновременно язык сценариев и командная оболочка, которая позволяет управлять системой и автоматизировать практически любую задачу. В книге «PowerShell для сисадминов» обладатель Microsoft MVP Адам Бертрам aka «the Automator» покажет, как использовать PowerShell так, чтобы у читателя наконец-то появилось время на игрушки, йогу и котиков. Вы научитесь: -Комбинировать команды, управлять потоком выполнения, обрабатывать ошибки, писать сценарии, запускать их удаленно и тестировать их с помощью фреймворка тестирования Pester. -Анализировать структурированные данные, такие как XML и JSON, работать с популярными сервисами (например Active Directory, Azure и Amazon Web Services), создавать системы мониторинга серверов. -Создавать и проектировать модули PowerShell. -Использовать PowerShell для удобной, полностью автоматизированной установки Windows. -Создавать лес Active Directory, имея лишь узел Hyper-V и несколько ISO-файлов. -Создавать бесчисленные веб- и SQL-серверы с помощью всего нескольких строк кода! Реальные примеры помогают преодолеть разрыв между теорией и работой в настоящей системе, а легкий авторский юмор упрощает чтение. Перестаньте полагаться на дорогое ПО и невнятные советы из сети!

Для кого эта книга
Эта книга предназначена для ИТ-специалистов и системных администраторов, которым надоело постоянно использовать один и тот же интерфейс и выполнять одну и ту же задачу в пятисотый раз за этот год. Также она будет полезна для инженеров DevOps, которые испытывают затруднения с автоматизацией новых серверных сред, выполнением автоматических тестов или автоматизацией конвейера непрерывной интеграции / непрерывной доставки (CI/CD).

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

Поток управления


Немного повторим. В главе 3 мы узнали, как можно комбинировать команды с помощью конвейера и внешних сценариев. В главе 2 рассмотрели переменные и как их использовать для хранения значений. Одним из основных преимуществ работы с переменными является возможность писать с их помощью код, который работает не со значением, а со «смыслом». Вместо того чтобы работать, например, с числом 3, вы будете работать с общим понятием $serverCount. За счет этого вы можете писать код, который работает одинаково, будь у вас один, два или тысяча серверов. Совместите эту способность с возможностью сохранять код в сценариях, которые можно запускать на разных компьютерах, и вы сможете начать решать задачи гораздо большего масштаба.

Однако в жизни порой имеет значение, работаете ли вы с одним сервером, с двумя или с тысячей. Пока что у вас нет подходящего способа учитывать это, и ваши сценарии работают просто «сверху вниз», не имея возможности адаптироваться в зависимости от определенных значений. В этой главе мы будем использовать поток управления и условную логику для написания сценариев, которые будут выполнять различные команды в зависимости от значений, с которыми они работают. К концу главы вы узнаете, как использовать операторы if/then и switch, а также различные циклы, чтобы придать вашему коду столь необходимую гибкость.

Немного о потоке управления

Мы напишем сценарий, который считывает содержимое файла, хранящегося на нескольких удаленных компьютерах. Чтобы продолжить работу, загрузите файл под названием App_configuration.txt из прилагаемых к книге материалов по ссылке github.com/adbertram/PowerShellForSysadmins/ и поместите его в корень диска C:\ на нескольких удаленных компьютерах. Если у вас нет удаленных компьютеров, пока просто продолжайте читать. В этом примере я буду использовать серверы с именами SRV1, SRV2, SRV3, SRV4 и SRV5.

Чтобы получить доступ к содержимому файла, воспользуемся командой Get-Content и укажем путь к файлу в значении аргумента параметра Path, как показано ниже:

Get-Content -Path "\\servername\c$\App_configuration.txt"

Для начала сохраним все имена наших серверов в массиве и запустим эту команду для каждого сервера. Откройте новый файл .ps1 и введите в него код из листинга 4.1.

Листинг 4.1. Извлечение содержимого файла с нескольких серверов

$servers = @('SRV1','SRV2','SRV3','SRV4','SRV5')
Get-Content -Path "\\$($servers[0])\c$\App_configuration.txt"
Get-Content -Path "\\$($servers[1])\c$\App_configuration.txt"
Get-Content -Path "\\$($servers[2])\c$\App_configuration.txt"
Get-Content -Path "\\$($servers[3])\c$\App_configuration.txt"
Get-Content -Path "\\$($servers[4])\c$\App_configuration.txt"

Теоретически, этот код должен работать без проблем. Но в этом примере предполагается, что у вас что-то идет не так. Что делать, если сервер SRV2 не работает? А если кто-то забыл положить App_configuration.txt на SRV4? А может, кто-то изменил путь к файлу? Вы можете написать отдельный сценарий для каждого сервера, но это решение не будет масштабироваться, особенно когда вы начнете добавлять все больше и больше серверов. Вам нужен код, который будет работать в зависимости от ситуации.

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

Мы начнем с рассмотрения самого простого типа потока управления — условного оператора.

Использование условных операторов

В главе 2 мы узнали, что существуют логические значения: истина и ложь. Логические значения позволяют создавать условные операторы, которые ставят задачу PowerShell выполнить определенный блок кода в зависимости от того, имеет ли выражение (называемое условием) значение True или False. Условие — это вопрос с вариантами ответов да/нет. У вас больше пяти серверов? Работает ли сервер 3? Существует ли путь к файлу? Чтобы начать использовать условные операторы, давайте посмотрим, как преобразовать такие вопросы в выражения.

Построение выражений с помощью операторов

Логические выражения можно писать с помощью операторов сравнения, которые сравнивают значения. Чтобы использовать оператор сравнения, нужно поместить его между двумя значениями, например:

PS> 1 –eq 1
True

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

-eq сравнивает два значения и возвращает True, если они равны.

-ne сравнивает два значения и возвращает True, если они не равны.

-gt сравнивает два значения и возвращает True, если первое больше второго.

-ge сравнивает два значения и возвращает True, если первое больше или равно второму.

-lt сравнивает два значения и возвращает True, если первое меньше второго.

-le сравнивает два значения и возвращает True, если первое меньше или равно второму.

-contains возвращает True, если второе значение является частью первого. Например, этот оператор позволяет определить, находится ли значение внутри массива.

В PowerShell есть и более продвинутые операторы сравнения. Здесь мы не будем на них останавливаться, но я рекомендую вам почитать о них в документации Microsoft по ссылке docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_comparison_operators или в разделе справки PowerShell (см. главу 1).

Вы можете использовать приведенные выше операторы для сравнения переменных и значений. Но выражение не обязательно должно быть сравнением. Иногда команды PowerShell можно использовать как условия. В предыдущем примере мы хотели узнать доступность сервера. С помощью командлета Test-Connection можно проверить наличие связи с сервером. Обычно в выходных данных командлета Test-Connection содержится много разной информации, но с помощью параметра Quiet вы можете заставить команду вернуть True или False, а с помощью параметра Count можно ограничить тест одной попыткой.

PS> Test-Connection -ComputerName offlineserver -Quiet -Count 1
False

PS> Test-Connection -ComputerName onlineserver -Quiet -Count 1
True

Чтобы узнать, отключен ли сервер, вы можете использовать оператор –not для преобразования выражения в противоположное:

PS> -not (Test-Connection -ComputerName offlineserver -Quiet -Count 1)
True

Теперь, когда вы познакомились с основными выражениями, давайте рассмотрим простейший условный оператор.

Оператор if

Оператор if работает просто: если выражение X истинно, то сделайте Y. Вот и все!

Чтобы использовать оператор в выражении, пишется ключевое слово if, за которым следуют круглые скобки, содержащие условие. После выражения следует блок кода, выделенный фигурными скобками. PowerShell выполнит этот блок кода только в том случае, если это выражение будет иметь значение True. Если выражение if имеет значение False либо вообще ничего не возвращает, блок кода не будет выполнен. Синтаксис оператора if/then показан в листинге 4.2.

Листинг 4.2. Синтаксис оператора if

if (условие) {
   # выполняемый код, если условие истинно
}

В этом примере есть немного нового синтаксиса: символ решетки (#) обозначает комментарий — это текст, который PowerShell игнорирует. Вы можете использовать комментарии, чтобы оставить полезные примечания и описания для себя или кого-нибудь, кто позже будет читать ваш код.

Теперь давайте еще раз посмотрим на код, показанный в листинге 4.1. Я расскажу вам о том, как использовать оператор if, чтобы не пытаться достучаться до неработающего сервера. В предыдущем разделе мы уже видели, что команду Test-Connection можно использовать в качестве выражения, которое возвращает True или False, поэтому сейчас давайте упакуем Test-Connection в оператор if, а затем воспользуемся командой Get-Content, чтобы не пытаться обращаться к неработающему серверу. Сейчас мы поменяем код только для первого сервера, как показано в листинге 4.3.

Листинг 4.3. Использование оператора if для выборочного обращения

$servers = @('SRV1','SRV2','SRV3','SRV4','SRV5')
if (Test-Connection -ComputerName $servers[0] -Quiet -Count 1) {
   Get-Content -Path "\\$($servers[0])\c$\App_configuration.txt"
}
Get-Content -Path "\\$($servers[1])\c$\App_configuration.txt"
--пропуск--

Поскольку у вас есть Get-Content в операторе if, вы не столкнетесь с какими-либо ошибками, если попытаетесь получить доступ к неработающему серверу; если тест завершится неудачно, ваш сценарий будет знать, что не следует пытаться считать файл. Код попытается получить доступ к серверу, только если он уже знает, что тот включен. Но обратите внимание, что этот код срабатывает только в том случае, если условие истинно. Достаточно часто вам нужно будет задать одно поведение сценария для истинного условия и другое для ложного. В следующем разделе вы увидите, как определить поведение для ложного условия с помощью оператора else.

Оператор else

Чтобы предоставить вашему оператору if альтернативу, можно использовать ключевое слово else после закрывающей скобки блока if, за которым будет следовать еще одна пара фигурных скобок, содержащая блок кода. Как показано в листинге 4.4, мы будем использовать оператор else, чтобы вернуть в консоль ошибку, если первый сервер не отвечает.

Листинг 4.4. Использование оператора else для запуска кода, если условие
не истинно

if (Test-Connection -ComputerName $servers[0] -Quiet -Count 1) {
   Get-Content -Path "\\$($servers[0])\c$\App_configuration.txt"
} else {
   Write-Error -Message "The server $($servers[0]) is not responding!"
}

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

Оператор elseif

Оператор else охватывает противоположную ситуацию: если if не срабатывает, значит, выполните это в любом случае. Такой подход работает для двоичных условий, то есть когда сервер либо работает, либо нет. Но иногда приходится иметь дело с большим числом вариантов. Например, предположим, что у вас есть сервер, на котором нет нужного вам файла, и вы сохранили имя этого сервера в переменной $problemServer (добавьте в свой сценарий эту строку кода!). Это означает, что вам нужна дополнительная проверка, позволяющая узнать, является ли сервер, который вы опрашиваете в данный момент, проблемным. Это можно реализовать с помощью вложенных операторов if, как показано в коде ниже:

if (Test-Connection -ComputerName $servers[0] -Quiet -Count 1) {
   if ($servers[0] –eq $problemServer) {
      Write-Error -Message "The server $servers[0] does not have the right
         file!"
   } else {
      Get-Content -Path "\\$servers[0]\c$\App_configuration.txt"
   }
} else {
   Write-Error -Message "The server $servers[0] is not responding!"
}
--пропуск--

Но есть и более аккуратный способ реализовать ту же логику — с помощью оператора elseif, который позволяет вам проверить дополнительное условие, перед тем как вернуться к коду в блоке else. Синтаксис блока elseif идентичен синтаксису блока if. Итак, чтобы проверить проблемный сервер с помощью оператора elseif, запустите код из листинга 4.5.

Листинг 4.5. Использование блока elseif

if (-not (Test-Connection -ComputerName $servers[0] -Quiet -Count 1)) { 
   Write-Error -Message "The server $servers[0] is not responding!"
} elseif ($servers[0] –eq $problemServer) 
   Write-Error -Message "The server $servers[0] does not have the right file!"
} else {
   Get-Content -Path "\\$servers[0]\c$\App_configuration.txt" 
}
--пропуск--

Обратите внимание, что мы не просто добавили оператор elseif, а заодно изменили логику кода. Теперь мы можем проверить, не находится ли сервер в автономном режиме, с помощью оператора –not. Затем, как только мы определили сетевой статус сервера, мы проверяем, является ли он проблемным. Если это не так, мы используем оператор else для запуска поведения по умолчанию — извлечения файла. Как видите, существует несколько способов структурировать код описанным образом. Важно то, что код работает и что он читабелен для человека со стороны, будь то ваш коллега, видящий его впервые, или вы сами спустя некоторое время после написания.

Вы можете объединить в цепочку сколько угодно операторов elseif, что позволяет учитывать самые разные сочетания обстоятельств. Однако операторы elseif являются взаимоисключающими: когда один из elseif принимает значение True, PowerShell запускает только его код и не проверяет остальные случаи. В листинге 4.5 это не вызвало никаких проблем, так как вам нужно было проверить сервер на предмет «проблемности» только после проверки работоспособности, но в дальнейшем я советую вам держать в уме эту особенность.

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

Оператор switch

Давайте немного подкорректируем наш пример. Допустим, у нас есть пять серверов, и на каждом сервере путь к нужному файлу различается. Исходя из того что вы знаете сейчас, вам придется создать отдельный оператор elseif для каждого сервера. Это сработает, но существует и более удобный метод.

Обратите внимание, что теперь мы будем работать с другим типом условия. Если раньше нам нужны были ответы на вопросы типа «да/нет», то теперь мы хотим получить конкретное значение одной вещи. Это сервер SRV1? SRV2? И так далее. Если бы вы работали только с одним или двумя конкретными значениями, оператор if подошел бы, но в данном случае оператор switch сработает гораздо лучше.

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

Листинг 4.6. Шаблон для оператора switch

switch (выражение) {
   значениевыражения {
      # Код
   }
   значениевыражения {
   }
   default {
     # Код, который выполняется при отсутствии совпадений
   }
}

Оператор switch может содержать практически неограниченное количество значений. Если выражение оценивается как значение, выполняется соответствующий код внутри блока. Важно то, что, в отличие от elseif, после выполнения одного блока кода PowerShell продолжит проверять и остальные условия, если не указано иное. Если ни одно из значений не подойдет, PowerShell выполнит код, указанный в блоке default. Чтобы прекратить перебор условий в операторе switch, используйте ключевое слово break в конце блока кода, как показано в листинге 4.7.

Листинг 4.7. Использование ключевого слова break в операторе switch

switch (выражение) {
   значениевыражения {
      # Код
      break
   }
--пропуск--

Ключевое слово break позволяет сделать условия в операторе switch взаимоисключающими. Вернемся к нашему примеру с пятью серверами и одним и тем же файлом, имеющим разные пути. Вы знаете, что сервер, с которым вы работаете, может иметь только одно значение (то есть он не может одновременно называться и SRV1, и SRV2), поэтому вам нужно использовать операторы break. Ваш сценарий должен выглядеть примерно так, как показано в листинге 4.8.

Листинг 4.8. Проверка различных серверов с помощью оператора switch

$currentServer = $servers[0]
switch ($currentServer) {
   $servers[0] {
      # Check if server is online and get content at SRV1 path.
      break
   }
   $servers[1] {
      ## Check if server is online and get content at SRV2 path.
      break
   }
   $servers[2] {
      ## Check if server is online and get content at SRV3 path.
      break
   }
--пропуск--

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

Использование циклов

Существует хорошее практическое правило для работы за компьютером: не повторяйся (don’t repeat yourself, DRY). Если вы обнаружите, что выполняете одну и ту же работу, то, скорее всего, существует способ ее автоматизировать. То же самое и с написанием кода: если вы используете одни и те же строки снова и снова, вероятно, существует решение получше.

Один из способов избежать повторов — использовать циклы. Цикл позволяет многократно выполнять код, до тех пор пока не изменится некоторое заданное условие. Условие остановки может запускать цикл заданное количество раз, либо до тех пор, пока не изменится некоторое логическое значение, либо определить бесконечное выполнение цикла. Каждый проход цикла мы будем называть итерацией.

PowerShell предлагает пять типов циклов: foreach, for, do/while, do/until и while. В этом разделе мы обсудим каждый тип цикла, отметим их уникальные черты и выделим лучшие ситуации для их использования.

Об авторе

Адам Бертрам (Adam Bertram) — опытный ИТ-специалист и эксперт в области интернет-бизнеса с 20-летним стажем. Предприниматель, ИТ-инфлюенсер, специалист Microsoft MVP, блогер, тренинг-менеджер и автор материалов по контент-маркетингу, сотрудничающий со многими ИТ-компаниями. Также Адам основал популярную платформу TechSnips для развития навыков ИТ-специалистов (techsnips.io).

Более подробно с книгой можно ознакомиться на сайте издательства
» Оглавление
» Отрывок

Для Хаброжителей скидка 25% по купону — PowerShell

По факту оплаты бумажной версии книги на e-mail высылается электронная книга.
Теги:книга
Хабы: Блог компании Издательский дом «Питер» Системное администрирование PowerShell Профессиональная литература
Всего голосов 6: ↑6 и ↓0+6
Просмотры5.7K

Похожие публикации

Лучшие публикации за сутки

Информация

Дата основания
Местоположение
Россия
Сайт
piter.com
Численность
201–500 человек
Дата регистрации

Блог на Хабре