Глава 13. Удалённое управление: один- к- одному и один- ко- многим

Давайте взглянем на команду Invoke-ScriptBlock. Обратите внимание, что она обладает параметром -ComputerName. Эй... а не значит ли это то, что она способна запускать команды также и в прочих хостах? После небольшого эксперимента вы обнаруживаете, что это в точности так. Сколько команд обладают способностью подключения к удалённым машинам? Хотя и не существует способа получения конкретного значения ответа на данный вопрос, их достаточно много.

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

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

Удалённое взаимодействие это гигантская, сложная технология. В этой главе мы выполним для вас введение в неё и рассмотрим ситуации, с которыми вы будете иметь дело от 80 до 90% своего времени. Однако мы не имеем возможности покрыть их абсолютно все, поэтому в самом конце этой главы в разделе Дальнейшее исследование мы укажем вам обязательные ресурсы, которые рассматривают настройки удалённого взаимодействия.

Основная мысль за удалённым PowerShell

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

Удалённое взаимодействие на устройствах Windows

PowerShell применяет протокол взаимодействия с названием Web Services for Management (WSMan). WSMan работает целиком поверх HTTP или HTTPS (HTTP по умолчанию), упрощая маршрутизацию через межсетевые экраны в случае их необходимости (поскольку каждый из таких протоколов пользуется для взаимодействия единственным портом). Реализация Microsoft для WSMon поступает в виде службы в фоновом режиме, Windows Remote Management (WinRM). WinRM по умолчанию устанавливается в устройствах Windows 10, а также в сервере 2012 и выше. По умолчанию, эти службы отключены, но запросто могут включаться индивидуально или групповой политикой.

Удалённое взаимодействие на устройствах macOS и Linux

Как вы могли догадаться, WSMan и WinRM это службы только для Windows. Поэтому, чтобы PowerShell обладал возможностями удалённого взаимодействия, его команда приняла решение что было бы лучше воспользоваться стандартном отрасли Безопасной оболочки (SSH, Secure Shell)/ SSH упрощает маршрутизацию через межсетевые экраны, в случае такой необходимости (потому как этот протокол применяет для взаимодействия единственный порт), и десятилетиями применялся профессионалами Linux. Microsoft портировал в Windows OpenSSH, а потому вы даже можете применять его для удалённого взаимодействия в Windows.

[Замечание]Настройка PSRP поверх SSH в Windows

Вы можете пожелать настроить протокол удалённого взаимодействия PowerShell (PSRP, PowerShell remoting protocol) поверх SSH в любой машине, в которой у вас имеется установленным PowerShell Core. Мы не хотим вдаваться в подробности того как поднять его, однако все инструкции доступны в документации Microsoft.

Кросс- платформенное удалённое взаимодействие

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

Зачем вам беспокоиться относительно того как возвращается такой вывод? Поскольку такие упорядоченные- и затем- развёрнутые объекты это всего лишь некого рода моментальные снимки; они не обновляются сами по себе непрерывно. Например, когда вы получили определённые объекты, которые представляют тот процесс, который запущен в удалённом компьютере, то что вы получили обратно будет в точности тем, что имелось в тот конкретный момент времени, в который был выработаны эти объекты. Такие объекты, как применение памяти и использование ЦПУ не будут обновляться чтобы отражать последующие условия. Кроме того, вы не можете заставлять свои развёрнутые объекты выполнять что бы то ни было - вы не можете указывать им останавливать себя, например.

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

  • Ваш компьютер, и тот, в который вы желаете отправлять команды, оба, должны исполнять PowerShell v7.1 или последующую версию.

  • В идеале, оба компьютера должны быть участниками одного и того же домена или доменам с двусторонним доверием. Существует возможность получения удалённого взаимодействия для работы вне домена, однако это слишком заумно и мы не будем обсуждать это в данной главе. Для изучения подробностей такой ситуации откройте PowerShell и выполните help about_remote_troubleshooting.

Испробуйте это сейчас Мы надеемся, что вы способны следовать некоторым примерам из этой главы. Для участия, вам в идеале потребуется второй тестовый компьютер (или виртуальная машина), которая пребывает в том же домене Active Directory, что и ваш проверочный компьютер, который вы применяли до сих пор. Если у вас установлен в этом втором компьютере PowerShell v7.1 или более поздний, вы можете запускать там любую версию Windows. Когда вы пользуетесь двумя устройствами Windows, ваша жизнь окажется намного легче, если они будут частью одного домена. Если вы не можете настроить дополнительные компьютер или виртуальную машину, для создания подключений удалённого взаимодействия с вашим текущим компьютером воспользуйтесь localhost. Вы всё ещё применяете удалённое взаимодействие, однако не столь волнующе "удалённо управлять" тем компьютером, за которым вы сидите.

Настройка PSRP поверх SSH

Давайте потратим некоторое время на настройку SSH в вашей среде.

macOS и Linux

В своём компьютере убедитесь что установлены необходимые сервер и клиент SSH. Вот эти инструкции в Ubuntu:


sudo apt install openssh-client
sudo apt install openssh-server
		

Для macOS такой клиент установлен по умолчанию. Вот команда для включения сервера:


sudo systemsetup -setremotelogin on
		

Далее нам необходимо установить тот модуль, который включает PSRP поверх SSH:


Install-Module EnableSSHRemoting
		

После этого выполните следующую команду для разрешений PSRP поверх SSH:


sudo pwsh -c Enable-SSHRemoting
		

Затем вам потребуется перезапустить соответствующую службу OpenSSH. В Ubuntu команда для перезапуска этой службы такая:


sudo service sshd restart
		

Вот эта команда для macOS:


sudo launchctl stop com.openssh.sshd
sudo launchctl start com.openssh.sshd
		

Настройка SSH в Windows

SSH может запускаться как в рабочих станциях, так и в серверах Windows. Если вы и в самом деле пожелаете (но мы не приветствуем делать это), вы можете отключить WinRM. Скорее всего, если вы применяете SSH для удалённого взаимодействия в устройстве Windows, вы имеете удалённое взаимодействие с устройством Linux либо macOS, или с них.

Установите клиент и сервер OpenSSH:


Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
		

Вот первоначальная настройка получаемого сервера SSH:


Start-Service sshd
Set-Service -Name sshd -StartupType 'Automatic'
		

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


Get-NetFirewallRule -Name *ssh*
		

Должно иметься правило с названием OpenSSH-Server-In-TCP, которое должно быть включено. Настройте и измените файл sshd_config, размещённый в $env:ProgramData\ssh в своей целевой машине (Рисунок 13.1)

 

Рисунок 13-1


Вот как выглядит файл sshd_config с добавленными изменениями PowerShell

Убедитесь что удалив символ # вы разрешили аутентификацию по паролю:


PasswordAuthentication yes
		

Добавьте Subsystem для PowerShell. Вы можете обратить внимание на то, что мы пользуемся короткими именами 8.3 для тех путей файлов, которые содержат пробелы.


Subsystem powershell c:/progra~1/powershell/7/pwsh.exe -sshs -NoLogo -NoProfile
		

Значением короткого названия для папки Program Files в Windows, это обычно Progra~1. Однако , чтобы убедиться, вы можете воспользоваться приводимой ниже командой:


Get-CimInstance Win32_Directory -Filter 'Name="C:\\Program Files"' | Select-Object EightDotThreeFileName
		

Вот необязательный ключ разрешения аутентификации по ключу:


PubkeyAuthentication yes
		

Перезапустите свою службу OpenSSH:


Restart-Service sshd
		
[Замечание]Убедитесь в безопасности своего сервера SSH

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

macOS

Ubuntu

Обзор PSRP поверх SSH

Давайте обсудим SSH, поскольку мы намерены настроить его для применения в удалённом взаимодействии. И снова, нам необходимо настроить PSRP поверх SSH - а также удалённое взаимодействие PowerShell - лишь в тех компьютерах, которые будут получать приходящие команды. В большинстве имеющихся окружений мы не работали с ними, поэтому ваши администраторы должны разрешить удалённое взаимодействие во всех компьютерах. Осуществив это вы получите возможность удалённой работы с рабочими станциями и ноутбуками клиентов в их фоновом режиме (что означает, что пользователи таких компьютеров не будут знать что вы делаете это), что может быть чрезвычайно полезным.

OpenSSH позволяет регистрировать большое число подсистем. Это делает возможным протоколировать работу по одному и тому же порту. Когда вы разрешаете удалённое взаимодействие SSH, PowerShell регистрируется в качестве некой подсистемы, а входящие подключения от PSRP перенаправляются в эту подсистему. Рисунок 13.2 иллюстрирует как всё складывается воедино.

 

Рисунок 13-2


Взаимосвязь между OpenSSH и PowerShell

Как показано, вы можете обладать в своей системе десятками и даже сотнями подсистем sshd. Всякий оконечный пункт может указывать на различные приложения.

Рисунок 13.2 иллюстрирует ожидающий (listener, прослушивающий) sshd. Действующий в качестве ожидающего sshd сидит и дожидается входящего запроса. Ожидающий "прослушивает" определённый порт по конкретному IP адресу.

Испробуйте это сейчас Пройдите далее и разрешите удалённое взаимодействие в своём втором компьютере (либо в первом, когда у вас имеется для работы лишь один). Если при включении удалённого взаимодействия вы получили сообщение об ошибке, остановитесь и решите это.

Обзор WinRM

Давайте поговорим про WinRM, ибо вы собираетесь настроить его для применения удалённого взаимодействия. И снова, вам требуется настроить WinRM - и удалённое взаимодействие PowerShell - только в тех компьютерах, которые получают приходящие команды. В большинстве имеющихся сред мы не работали с ними, поэтому ваши администраторы должны разрешить удалённое взаимодействие во всех компьютерах на основе Windows (имейте в виду, что PowerShell и удалённое взаимодействие поддерживаются всеми по пути вплоть до Windows XP). Выполнив это вы получите возможность удалённого взаимодействия с настольными компьютерами и ноутбуками клиентов в их фоновом режиме (что подразумевает, что пользователи таких компьютеров даже не знают что вы делаете это), что может быть очень полезным.

WinRM уникален для PowerShell. Microsoft начала применять его всё чаще и чаще для административного взаимодействия - даже для того, что применяет в наши дни иные протоколы. Что следует иметь в виду, так это то, что Microsoft сделала WinRM способным выполнять маршрутизацию обмена для множества административных приложений - не только для PowerShell. WinRM действует как диспетчер: по мере поступления обмена WinRM принимает решение с каким из приложений следует иметь дело и такие приложения должны регистрироваться как конечные точки (endpoints) в WinRM с тем, чтобы WinRM ожидал бы (прослушивал бы) входящий обмен от их имени. Это означает, что вам необходимо не только включить WinRM, но также и сообщить о регистрации PowerShell в качестве конечного пункта в WinRM. Рисунок 13.3 иллюстрирует как все части соединяются друг с другом.

 

Рисунок 13-3


Взаимодействие между WinRM, WSMan, конечными точками и PowerShell

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

Рисунок 13.3 также иллюстрирует собственно приёмник (listener) WinRM, который на данном рисунке относится к разновидности HTTP. Приёмник сидит и ждёт входящий сетевой обмен от имени WinRM - нечто подобное прослушиванию вебсервером входящих запросов. Приёмник "ждёт" по определённому порту и заданному IP адресу, хотя создаваемый по умолчанию Enable-PSRemoting приёмник прослушивает все локальные IP адреса.

Такой приёмник соединяется с определённой вами конечной точкой. Один из способов создания некой конечной точки заключается в открытии какой- то копии PowerShell - убедитесь что вы запустили его от имени администратора - и исполнить командлет Enable-PSRemoting. Порой вы можете обнаруживать ссылку на иной командлет, с названием Set-WSManQuickConfig. Вам не следует запускать его; за вас его вызовет Enable-PSRemoting, а Enable-PSRemoting выполнит несколько дополнительных шагов, которые необходимы для получения удалённого взаимодействия поднятым и функционирующим. В общем, этот командлет запустит службу WinRM, настроит её автоматический запуск, зарегистрирует PowerShell в качестве конечной точки и даже настроит исключение межсетевого экрана Windows для разрешения входящего обмена WinRM.

Испробуйте это сейчас Проследуйте далее и разрешите удалённое взаимодействие в своём втором компьютере (или в самом первом, если он единственный, с которым вы можете работать). Убедитесь что вы запустили PowerShell от имени администратора если вы в устройстве Windows (в строке заголовка окна должно быть прописано Администратор - Administrator). Если это не так, закройте свою оболочку, кликните правой кнопкой по иконке PowerShell в меню Start и выберите Run as Administrator в меню контекста. {Прим. пер.: по умолчанию в большинстве систем так будет запущен Windows PowerShell, для запуска PowerShell Core, если у вас нет для него заблаговременно созданной иконки, наберите в строке поиска PowerShell и запустите v7.1 (v7.2).}

Наиболее распространённой ошибкой, которую вы получаете, это "WinRM firewall exception will not work since one of the network connection types on this machine is set to Public". Все установленные в Public сетевые подключения не способны обладать исключениями межсетевого экрана Windows, а потому когда Enable-PSRemoting пытается его создать, это завершается отказом. Единственным решением является проход в Windows и изменение настроек соответствующего сетевого адаптера с тем, чтобы любая сетевая среда, в которой вы находитесь, была бы либо рабочей, либо домашней. Но не делайте этого когда вы подключены к общедоступной сетевой среде (например, к общедоступной беспроводной точке доступа), потому как вы отключите некоторые значимые свойства безопасности.

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

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

Если вас не прельщает беготня по всем компьютерам для включения удалённого взаимодействия, не беспокойтесь: вы также способны осуществить это через Объект групповой политики (GPO, Group Policy Object). Необходимые настройки GPO встроены в ваши Контроллеры домена (вы можете выгрузить шаблон ADM для добавления таких настроек GPO в более ранние контроллеры домена). Откройте GPO и загляните в Computer Configuration > Administrative Templates > Windows Components. На данный момент мы полагаем что вы исполнили Enable-PSRemoting в тех компьютерах, которые вы хотите настраивать, потом как в этот момент вы, скорее всего выполняете воспроизведение только на одной или двух виртуальных машинах.

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

Тема подсказки about_remote_troubleshooting PowerShell содержит более подробные сведения о применении объектов Групповой политики. Отыщите разделы "How to enable remoting in an enterprise" и "How to enable listeners by using a Group Policy" внутри этой подсказки.

Применение Enter-PSSession и Exit-PSSession для удалённой работы один- к- одному

PowerShell применяет удалённое взаимодействие двумя различными способами. Первый это удалённое взаимодействие один- к- одному. Второй это удалённое взаимодействие один- ко- многим (вы ознакомитесь с ним в нашем следующем разделе). При удалённом взаимодействии один- к- одному вы выполняете доступ к приглашению на ввод оболочки в отдельном удалённом компьютере. Все выполняемые вами команды запускаются непосредственно в этом компьютере, а вы наблюдаете результаты в окне своей оболочки. Это отчасти напоминает применение SSH или Remote Desktop Connection, за исключением того, что вы ограничены средой командной строки Windows PowerShell. Такой вид удалённого взаимодействия также пользуется некой фракцией тех ресурсов, которые требуются Удалённому рабочему месту (Remote Desktop), а потому выставляет намного меньшие накладные расходы для ваших серверов.

Прежде чем подключаться к некому удалённому компьютеру, нам необходимо разобраться с отличием между параметрами -hostname и -computername:

  • -hostname - Применяйте его при использовании SSH.

  • -computername - Применяйте его для подключения через WinRM.

PowerShell не обладает способом узнать какой протокол вы пытаетесь применять, поэтому вам придётся сообщать о нём. Для установления подключения один- к- одному с удалённым компьютером выполните такую команду:


Enter-PSSession -HostName Ubuntu1 -UserName tylerl
Enter-PSSession -ComputerName SRV2 -UserName contoso\tylerl
		

В качестве альтернативы вы можете пользоваться следующим синтаксисом:


Enter-PSSession -HostName tylerl@Ubuntu1
		

(Вместо SRV2 или Ubuntu1 вам надлежит применять правильное название.)

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


[Ubuntu1] PS /home/tylerl>

[SRV2] PS C:\>
		

Такое приглашение оболочки сообщает вам, что всё что вы осуществляете, имеет место в Ubunut1, (либо в том сервере, к которому вы подключены). Вы можете выполнять ту команду, которую пожелаете. Вы даже способны импортировать модули.

Испробуйте это сейчас Попробуйте создать удалённое подключение к своему второму компьютеру или виртуальной машине. Если вам не удалось выполнить этого, перед тем как вы попытаетесь подключаться к нему, вам также потребуется разрешить удалённое взаимодействие и в том компьютере. Обратите внимание, что вам требуется знать имя хоста или IP адрес.

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

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

Помимо этого довольно незначительного предостережения, вы должны быть готовыми к продолжению. Но постойте - что вам делать когда вы завершите выполнять команды на удалённом компьютере Многие командлеты следуют парами: один командлет делает нечто, а другой - противоположное. В данном случае, раз Enter-PSSession доставляет вас в удалённый компьютер, можете ли вы угадать что выведет вас из этого удалённого компьютера? Возьмите пирожок с полки, если вы догадались что это Exit-PSSession. Этой команде не требуются никакие параметры; исполните её и приглашение в вашей командной оболочке вернётся в нормальное состояние, а удалённое подключение автоматически закроется.

Испробуйте это сейчас Если вы создали ранее удалённый сеанс, покиньте его. На данный момент мы покончили с ним.

Что если вы позабыли выполнить что это Exit-PSSession и вместо этого закрыли своё окно PowerShell Не беспокойтесь. PowerShell достаточно сообразителен чтобы уяснить что вы сделали и ваше удалённое соединение закроется само.

Мы обязаны сделать одно предостережение: Когда вы осуществляете удалённое взаимодействие с неким компьютером, не выполняйте что это Exit-PSSession с этого компьютера, пока вы полностью не осознаете что вы делаете. Допустим, вы работаете в Компьютере A под управлением Ubuntu, и вы выполняете удалённое взаимодействие с SRV2. Затем, из своего приглашения PowerShell вы выполняете следующее:


[Ubuntu1] PS /home/tylerl> Enter-PSSession -computername SRV2 -UserName contsco\tylerl
		

Это вызывает установление открытия подключения к SRV2 из Ubunru1, что может начать создание некой удалённой цепочки, которую сложно продолжать отслеживать и которая выставляет не нужные накладные расходы для ваших серверов. Порой вам, возможно, придётся делать это - мы полагаем, в целом, когда такой компьютер как SRV2 пребывает за межсетевым экраном, и вы не способны получать к нему непосредственный доступ, а потому вы пользуетесь SRV1 в качестве посредника для перехода к Server-DC4. Но, в качестве основного правила, старайтесь избегать удалённых цепочек. По адресу http://mng.bz/AxXe у команды PowerShell имеется отличная статья о создании второго прыжка при удалённом взаимодействии PowerShell.

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

Некоторые люди называют удалённую цепочку вторым прыжком (second hop) и именно в этом состоит основной глюк PowerShell. Даём подсказку: когда в приглашении на ввод PowerShell отображается имя компьютера, это означает что всё готово. Вы не сможете больше выполнять команды удалённого управления, пока не покинете данный сеанс и не "вернётесь" в свой компьютер.

Когда вы пользуетесь удалённым взаимодействием один- к- одному, вам нет нужды беспокоиться об упорядочении и распаковке. Как вы знаете, вы выполняете набор непосредственно в консоли удалённого компьютера. Когда вы извлекаете некий процесс и передаёте его конвейером в Stop-Process, он закончит исполнение, как вы и ожидали.

Применение Invoke-ScriptBlock для удалённой работы один- ко- многим

Наш следующий трюк - и, честно говоря, это одна из самых крутых вещей в PowerShell - это отправка команды во множество удалённых компьютеров одновременно. Да, верно, полномасштабные распределённые вычисления. Каждый компьютер самостоятельно выполнит команду и отправит вам результаты обратно. Всё это выполняется при помощи командлета Invoke-ScriptBlock и носит название удалённого взаимодействия одного- ко- многим, или 1:N. Соответствующая команда выглядит так:


Invoke-ScriptBlock -ComputerName SRV2,DC3,SRV4 -ScriptBlock { Get-Process pwsh } -UserName tylerl
		

Испробуйте это сейчас Выполните эту команду. Выполните замену необходимым названием своего удалённого компьютера (или компьютеров) и имени пользователя там, где мы поместили названия своих трёх серверов.

Всё что представлено в фигурных скобках ({}) передаётся в указанные удалённые компьютеры- во все три. По умолчанию, PowerShell общается за раз с вплоть до 32 компьютеров; если вы определите больше, он поместит их в очередь и, как только один из компьютеров завершит, начнёт выполнение следующий по очереди. Если вы обладаете внушительной сетевой средой и мощными компьютерами, вы можете увеличить это число, через определение для Invoke-ScriptBlock параметра -throttleLimit. Для получения дополнительных сведений ознакомьтесь с подсказкой этой команды.

[Предостережение]Будьте внимательны с правописанием

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

Давайте рассмотрим некий образец:


Invoke-ScriptBlock -HostName SRV2,DC3,SRV4 -ScriptBlock { Get-Process pwsh | Where-Object {$_.Parent.ProcessName -like '*term*'}} -UserName
		

В нём фигурными скобками две команды пользуются: Invoke-ScriptBlock и Where-Object. Where-Object целиком вложена внутри внешней пары скобок. Самый внешний набор скобок заключает в себе всё, что подлежит отправке для исполнения в удалённые компьютеры:


Get-Process pwsh | Where-Object {$_.Parent.ProcessName -like '*term*'}
		

Соблюдение такой команды может оказаться затруднительным, в особенности в такой книге как эта, где физическая ширина страницы заставляет отображать данную команду в нескольких строках текста. {Прим. пер.: наше изложение в html лишено данного недостатка.}

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

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

Испробуйте это сейчас Убедитесь что вы способны выявить параметр -ScriptBlock в тексте подсказки Invoke-ScriptBlock и что вы можете подсветить тот параметр, который позволит вам указать путь и имя файла вместо блока сценария.

Мы хотим вернуться обратно к параметру -HostName, о котором мы упоминали в самом начале этой главы. Когда мы впервые применили Invoke-ScriptBlock, мы набирали разделённый запятой список имён хостов, как мы это делали в своём предыдущем примере. Однако мы работаем с большим числом компьютеров и мы не хотим набирать их всякий раз. Для некоторых общих категорий компьютеров мы составляем текстовые файлы, например, для веб серверов и контроллеров доменов. Каждый такой файл содержит имена компьютеров по одному в строке, и это всё - никаких запятых, никаких кавычек, ничего. PowerShell упрощает для нас применение таких файлов:


Invoke-ScriptBlock -ScriptBlock { dir } -HostName (Get-Content webservers.txt) -UserName tylerl
		

Указанные здесь скобки заставляют PowerShell вначале выполнить команду Get-Content - в точности также как при арифметических вычислениях. Полученные результаты Get-Content затем выставляется стеком в своём параметре -HostName, который выполнятся для каждого перечисленного в этом файле компьютера.

Различия между удалёнными и локальными командами

Мы хотим дать пояснения об имеющихся различиях между исполнением команд с применением Invoke-ScriptBlock и работой тех же самых команд локально, а также об имеющейся разнице между удалённым взаимодействием и прочими видами связи. Для данного обсуждения мы воспользуемся в качестве своего примера этой командой:


Invoke-ScriptBlock -HostName SRV2,DC3,SRV4 -ScriptBlock { Get-Process pwsh -UserName tylerl | Where-Object {$_.Parent.ProcessName -like '*term*'}}
		

Преобразованные из последовательных в параллельные объекты

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

Например, выполните это в своём локальном компьютере и вы заметите, что объект System.Diagnostics.Process обладает большим числом связанных с ним методов:


PS > Get-Process | Get-Member

TypeName: System.Diagnostics.Process

Name                       MemberType     Definition 
----                       ----------     ----------
Handles                    AliasProperty  Handles = Handlecount
Name                       AliasProperty  Name = ProcessName
NPM                        AliasProperty  NPM = NonpagedSystemMemory...
PM                         AliasProperty  PM = PagedMemorySize64
SI                         AliasProperty  SI = SessionId
VM                         AliasProperty  VM = VirtualMemorySize64
WS                         AliasProperty  WS = WorkingSet64
Parent                     CodeProperty   System.Object Parent{get=G...
Disposed                   Event          System.EventHandler Dispos...
ErrorDataReceived          Event          System.Diagnostics.DataRec...
Exited                     Event          System.EventHandler Exited...
OutputDataReceived         Event          System.Diagnostics.DataRec...
BeginErrorReadLine         Method         void BeginErrorReadLine()
BeginOutputReadLine        Method         void BeginOutputReadLine()
CancelErrorRead            Method         void CancelErrorRead()
CancelOutputRead           Method         void CancelOutputRead()
Close                      Method         void Close()
CloseMainWindow            Method         bool CloseMainWindow()
Dispose                    Method         void Dispose(), void IDisp...
Equals                     Method         bool Equals(System.Object ...
GetHashCode                Method         int GetHashCode()
GetLifetimeService         Method         System.Object GetLifetimeS...
GetType                    Method         type GetType()
InitializeLifetimeService  Method         System.Object InitializeLi...
Kill                       Method         void Kill(), void Kill(boo...
Refresh                    Method         void Refresh()
Start                      Method         bool Start()
ToString                   Method         string ToString()
WaitForExit                Method void    WaitForExit(), bool W...
WaitForInputIdle           Method bool    WaitForInputIdle(), b...
__NounName                 NoteProperty   string __NounName=Process
		

Теперь давайте получим некоторые из тех же самых объектов через удалённое взаимодействие:


PS > Invoke-ScriptBlock {Get-Process} -HostName localhost -UserName tylerl | Get-Member

TypeName: Deserialized.System.Diagnostics.Process

Name                       MemberType     Definition
----                       ----------     ----------
GetType                    Method         type GetType()
ToString                   Method         string ToString(), string To...
Company                    NoteProperty   object Company=null
CPU                        NoteProperty   object CPU=null
Description                NoteProperty   object Description=null
FileVersion                NoteProperty   object FileVersion=null
Handles                    NoteProperty   int Handles=0
Name                       NoteProperty   string Name=
NPM                        NoteProperty   long NPM=0
Parent                     NoteProperty   object Parent=null
Path                       NoteProperty   object Path=null 
PM                         NoteProperty   long PM=0
Product                    NoteProperty   object Product=null
ProductVersion             NoteProperty   object ProductVersion=null
PSComputerName             NoteProperty   string PSComputerName=localh...
PSShowComputerName         NoteProperty   bool PSShowComputerName=True
RunspaceId                 NoteProperty   guid RunspaceId=26297051-1cb...
SI                         NoteProperty   int SI=53860
VM                         NoteProperty   long VM=0
WS                         NoteProperty   long WS=0
__NounName                 NoteProperty   string __NounName=Process
BasePriority               Property       System.Int32 {get;set;}
Container                  Property       {get;set;}
EnableRaisingEvents        Property       System.Boolean {get;set;}
		

Все методы - за исключением универсальных методов ToString() и GetType(), общих для всех объектов - исчезли. Это копия для объекта, доступного исключительно для считывания; вы не способны заставлять их выполнять такие вещи как останов, пауза, возобновление и т.п.. Тем самым, любые действия, которые вы бы желали осуществить в результате своей команды, должны быть включены в отправляемый в удалённый компьютер блок сценария; именно так эти объекты останутся в рабочем состоянии и будут содержать все свои методы.

Сопоставление локальной и удалённой обработки

Мы процитируем свой первоначальный пример снова:


Invoke-ScriptBlock -HostName SRV2,DC3,SRV4 -ScriptBlock { Get-Process pwsh -UserName tylerl | Where-Object {$_.Parent.ProcessName -like '*term*'}}
		

Вот что здесь происходит:

  • Контакты с компьютерами производятся параллельно, что означает, что эта команда может быть выполнена до некоторой степени более быстро.

  • Все запросы необходимых записей компьютеров выполняются и фильтруются локально. Передаются по их сетевой среде лишь те результаты, которые отфильтрованы, что означает, что передаются лишь представляющие наш интерес сведения.

  • Перед передачей каждый компьютер упорядочивает свой вывод в XML. Наш компьютер получает этот XML и выполняет его раскрытие обратно в нечто, что выглядит как объект. Однако это не является реальными объектами журнала событий и это ограничивает то, что мы можем осуществлять с ними в своём компьютере.

Теперь сопоставим это с такой альтернативой:


Invoke-ScriptBlock -HostName SRV2,DC3,SRV4 -ScriptBlock { Get-Process pwsh } -UserName tylerl | Where-Object {$_.Parent.ProcessName -like '*term*'}
		

Имеющиеся отличия едва уловимы. Мы наблюдаем лишь одну разницу: мы переместили одну из своих фигурных скобок.

В нашей второй версии удалённо активируется лишь Get-Process. Все те результаты, которые вырабатываются Get-Process упорядочиваются и отправляются в наш компьютер, в котором они распаковываются в объекты и затем конвейером отправляются в Where и фильтруются. Наша вторая версия команды менее действенна, поскольку по сетевой среде передаётся множество ненужных сведений, причём нашему единственному компьютеру приходится фильтровать получаемые от трёх компьютеров результаты, вместо того чтобы эти три компьютера фильтровали бы для нас самостоятельно свои результаты. Такая вторая версия, следовательно, плохая мысль.

Давайте рассмотрим вторые версии другой команды, начинающейся следующим образом:


Invoke-ScriptBlock -ComputerName SRV2 -ScriptBlock { Get-Process -name pwsh } -UserName tylerl | Stop-Process
		

Теперь взглянем на вторую версию:


Invoke-ScriptBlock -ComputerName SRV2 -ScriptBlock { Get-Process -name pwsh -UserName tylerl | Stop-Process }
		

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

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

Основная мораль данной истории состоит в том, что всегда осуществляйте в своей обработке на удалённом компьютере столько, сколько возможно. Единственное что вы должны ожидать для осуществления с получаемыми от Invoke-ScriptBlock результатами, это их отображение в качестве отчёта, либо некого файла данных и тому подобного. Такому совету следует наша вторая версия: в наш удалённый компьютер отправляется Get-Process -name pwsh | Stop-Process, а потому эта команда целиком - и получение необходимого процесса и его останов - происходят в таком удалённом компьютере. По той причине, что Stop-Process обычным образом не производит никакого вывода, не будет никаких объектов для их упорядочения и отправки к нам, а потому в своей локальной консоли мы не будем видеть ничего. Однако эта команда осуществит то что мы желали: остановит необходимый процесс pwsh в нашем удалённом компьютере , а не в нашей локальной машине.

Всякий раз, когда мы пользуемся Invoke-ScriptBlock, мы всегда рассматриваем эти команды после этого. Когда мы видим команды для форматирования или для экспорта данных, всё отлично, потому как допустимо выполнять такие вещи с получаемыми от Invoke-ScriptBlock результатами. Однако если за Invoke-ScriptBlock следует командлет действия - коим выступает запуск, останов, настройка, изменение или исполнение ещё чего- то - тогда мы откидываемся на спинку кресла и пытаемся понять что мы осуществляем. В идеале мы бы желали чтобы все эти действия происходили в нашем удалённом компьютере, а не в нашем локальном компьютере.

Но постойте, есть ещё что-то

Во всех предыдущих примерах применялись одноранговые соединения удалённого взаимодействия, то есть мы указывали имена хостов. Если вы собираетесь повторно подключаться к одному и тому же компьютеру (компьютерам) многократно в течении короткого промежутка времени, вместо этого вы можете применять повторно используемые постоянные соединения. Эту технику мы рассмотрим в Главе 18.

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

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

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

  • Удалённое взаимодействие разрабатывается с тем, чтобы быть более- менее автоматически настраиваемым. Когда все компьютеры вовлечены в один и тот же домен, и ваше имя пользователя одно и то же, обычно всё срабатывает отлично. Если это не так, для погружения в подробности вам необходимо выполнить help about_remote_troubleshooting.

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

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

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

Для данных лабораторных занятий вам требуется компьютер с запущенным PowerShell v7 или позднее. В идеале вы должны иметь два компьютера в одной и той же сетевой среде с включённым удалённым взаимодействием.

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

  1. Выполните подключение один- к- одному с удалённым компьютером (или с localhost, если у вас имеется лишь один компьютер). Запустите предпочитаемый вами тестовый редактор. Что произошло?

  2. При помощи Invoke-ScriptBlock выполните выборку списка запущенных в данный момент процессов из одного или нескольких удалённых компьютеров (если у вас имеется лишь один компьютер, удовлетворимся применением localhost дважды). Отформатируйте получаемые результаты в виде широкого списка. (Совет: Будет нормально если вы выполните выборку результатов и отформатировать их после появления в вашем компьютере - не включайте результаты командлетов localhost в тех командах, которые выполняются удалённо.)

  3. Воспользуйтесь Invoke-ScriptBlock для получения списка верхних 10 процессов по использованию виртуальной памяти. Если у вас есть такая возможность, сделайте своей целью один или два удалённых компьютера; если у вас имеется лишь один компьютер, воспользуйтесь дважды целью localhost.

  4. Создайте текстовый файл, который содержит три названия компьютеров, по одному имени в строке. Будет нормально воспользоваться одним и тем же именем компьютера, или localhost, три раза, когда у вас имеется доступ лишь к одному компьютеру. Затем воспользуйтесь Invoke-ScriptBlock для выборки 10 самых новых файлов из вашего домашнего каталога (~)/

  5. Применив Invoke-ScriptBlock, запросите у одного или более компьютеров отображение свойства PSVersion из их переменной $PSVersionTable. (Подсказка: это потребует от вас получения соответствующего свойства некого элемента.)

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

  1. 
    Enter-PSSession Server01
    [Ubuntu1] /home/tylerl> nano 
    		

    Будет запущен процесс nano, однако у нас не будет никакого интерактивного процесса ни локально, ни удалённо. На самом деле, при подобном запуске соответствующее приглашение на ввод не будет возвращено до тех пор, пока не завершится такой процесс nano - хотя некой альтернативой команды запуска выступает Start-Process nano.

    
    [SRV2] PS C:\Users\Administrator\Documents> Notepad 
    		

    Будет запущен процесс Notepad, однако у нас не будет никакого интерактивного процесса ни локально, ни удалённо. На самом деле, при подобном запуске соответствующее приглашение на ввод не будет возвращено до тех пор, пока не завершится такой процесс Notepad - хотя некой альтернативой команды запуска выступает Start-Process Notepad.

  2. 
    Invoke-ScriptBlock –scriptblock {Get-Process } -HostName Server01,Server02 -UserName yourUser | Format-Wide -Column 4
    		
  3. 
    Invoke-ScriptBlock -scriptblock {get-process | sort VM -Descending | Select-first 10} –HostName Server01,Server02 -UserN
    		
  4. 
    Invoke-ScriptBlock -scriptblock { Get-ChildItem ~/* | Sort-Object -Property LastWriteTime -Descending | Select-Object -First 10} -HostName (Get-Content computers.txt) -UserName yourUser
    		
  5. 
    Invoke-ScriptBlock –scriptblock $ -Server01,Server02 -UserName yourUser
    		

Дальнейшее исследование

Мы бы могли рассказать намного больше об удалённом взаимодействии с PowerShell - достаточно чтобы вы ещё месяц читали об этом во время обеденных перерывов. К сожалению, некоторые из его наиболее сложных частей плохо задокументированы. Мы предлагаем вам зайти на ресурс powerShell.org и, в частности, в их ресурсы электронных книг, где Дон и его последователь MVP доктор Тобиас Вельтнер составили для вас всеобъемлющую (и бесплатную!) мини- электронную книгу (см. Secrets of PowerShell Remoting). В этом руководстве иными словами изложены некоторые основы, которые вы изучили в данной главе, но первичное внимание в нём уделяется подробным пошаговым инструкциям (с цветными снимками экрана), которые показывают как настраивать различные сценарии удалённого взаимодействия. В этом руководстве к тому же рассматриваются некоторые более сложные подробности изучаемого протокола и устранения неполадок, а также имеется кратких раздел о том, как обсуждать со специалистами по информационной безопасности вопросы удалённого взаимодействия. Данное руководство периодически обновляется, поэтому проверяйте его каждые несколько месяцев, чтобы убедиться, что у вас имеется самая последняя его версия.