Удаленное взаимодействие (Remoting) — одна из самых полезных и замечательных возможностей Windows PowerShell. В этом выпуске колонки мы копнем удаленное взаимодействие поглубже, разберемся, как оно работает, и посмотрим, как его можно превратить в эффективный и ценный производственный инструмент.
Приступаем к удаленному взаимодействию
Прежде всего, надо включить удаленное взаимодействие на всех компьютерах, к которым планируется обращаться удаленно. Для этого надо либо выполнить командлет Enable-PSRemoting на целевом компьютере, либо настроить удаленное взаимодействие средствами групповой политики. Чтобы получить инструкции, можно выполнить команду about_remote_troubleshooting в любой копии Windows PowerShell v2.
Для удаленного взаимодействия не обязательно устанавливать Windows PowerShell версии 2. Для любой версии Windows вплоть до Windows XP оболочку можно загрузить с веб-сайта Microsoft. При использовании удаленного взаимодействия открывается порт TCP на компьютерах, где оно разрешено. Если в системе есть брандмауэр Windows, необходимое разрешение позволит создать командлет Enable-PSRemoting.
Удаленное взаимодействие в режиме «один к одному»
Самый простой вариант использования удаленного взаимодействия — в интерактивной оболочке, им во многом таким же образом, как в Secure Shell (SSH) в системах Unix или Linux. Выполните команду Enter-PSSession –computernameserver, где server — это имя удаленного компьютера.
Нужно использовать только настоящее имя компьютера, не псевдоним и не IP-адрес. Это будет работать «без проблем» сразу после включения удаленного взаимодействия только в доменной среде, где для взаимной проверки подлинности вас и удаленной машины используется Kerberos. В среде без доменов нужно настроить компьютеры, как описано в справочной статье about_remote_troubleshooting.
Обратите внимание, что ваши удостоверения делегируются удаленному компьютеру. Все выполняемые вами команды будут работать в контексте ваших идентификационных данных, а не какой-то всесильной системной учетной записи. Делегировать удостоверения по цепочке при переходе на еще один компьютер нельзя, поэтому в общем случае нельзя удаленно взаимодействовать с еще одним компьютером, пока открыто окно удаленного взаимодействия. Чтобы закрыть подключение и вернуться на локальный компьютер, выполните команду Exit-PSSession.
Удаленное взаимодействие в режиме «один ко многим»
Настоящая мощь удаленного взаимодействия заключается в возможности отправить команду параллельно нескольким компьютерам. Каждый удаленный компьютер выполнит команду, сериализует результирующий объект в XML и по сети вернет результат на ваш компьютер.
Получив этот XML-код, ваш компьютер десериализует его обратно в статический объект. Это позволяет работать с результатами команды почти так же, как с обычными результатами.
Все начинается с командлета Invoke-Command. В самой простом случае надо указать команду для выполнения в форме блока сценария и компьютеры, на которых надо ее выполнить. Например, следующий командлет считывает список имен компьютеров из текстового файла (по одному имени на строку) и выполняет на них команду:
Invoke-Command –scriptblock { Get-EventLog Security –newest 200 }
–computername (Get-Content computernames.txt)
В возвращенных результатах будет дополнительное свойство по имени PSComputerName — оно позволяет понять, с какого компьютера пришел результат. Это удобно, так как результаты могут приходить в порядке, отличном от порядка следования имен в файле.
Это свойство можно использовать для сортировки, группировки, фильтрации и другой обработки результата. Старайтесь избегать сортировки, если возвращенных данных очень много, так как командлету Sort-Object придется скопировать результат в кеш и выполнять сортировку уже там.
В Invoke-Command есть также параметр –FilePath. Его можно использовать вместо –ScriptBlock для определения сценария, а не двух-трех команд. Есть также параметры, позволяющие задавать разные удостоверения или переопределять значения по умолчанию:
- –Credential позволяет задать имя пользователя, а пароль запрашивается во время выполнения. В контексте этого пользователя будет выполнено подключение удаленному компьютеру и выполнена команда или сценарий. Можно также предоставить объект Credential, созданный командой Get-Credential.
- –Port позволяет задать порт, отличный от заданного по умолчанию. Используйте этот параметр, если перенастроили службу удаленного управления Windows (Windows Remote Management, WinRM) на прослушивание другого порта.
- –UseSSL принуждает к шифрованию подключения и использованию другого порта TCP (подобно тому, как в HTTPS используется порт, отличный от порта нешифрованного HTTP).
- –ThrottleLimit задает максимальное число компьютеров, на которых параллельно может выполняться команда. По умолчанию этот параметр равен 32. Это значение успешно прошло тестирование в довольно больших средах, а его повышение вызовет повышенную нагрузку на процессор и память вашего компьютера, поэтому эту операцию нужно выполнять с большой осторожностью.
Передача входных данных в удаленные командах
В Invoke-Command есть два дополнительных параметра, о которых часто забывают. Первый — –ArgumentList; он может использоваться только в связке с –ScriptBlock (но не –FilePath). Параметр –ArgumentList предназначен для передачи локальных переменных с локального компьютера в команду, пересылаемую на удаленные компьютеры.
В блоке сценария определяется блок параметров, где декларируются переменные, которые должны использоваться на удаленных компьютерах. В эти переменные позже передается список аргументов. Вот пример:
Invoke-Command –computername SERVER1 –scriptblock { param($one,$two) Get-EventLog –logname $one –newest $two } –ArgumentList $log,$quantity
Здесь сценарий передает содержимое локальной переменной $log в переменную $one и использует ее для определения имени получаемого журнала. Затем локальная переменная $quantity передается в переменную $two и используется для указания числа записей журнала событий, которые надо вернуть. Передача аргументов выполняется исключительно согласно порядку переменных: $log передается в $one, потому что они обе указаны первыми, а $quantity передается в $two, так как они обе стоят на втором месте.
Параметр –InputObject — еще один способ передачи входных данных на удаленные компьютеры; он поддерживает оба параметра:и –ScriptBlock, –FilePath. Все объекты, указанные в параметре –InputObject, передаются удаленной команде или сценарию в специальной переменной $input.
Получение выходных данных в удаленных команд
При выполнении одной простой команды, такой как Get-EventLog, результаты работы команды вы получите из Invoke-Command. Например, если надо сбросить все выходные данные в XML-файл для последующего анализа, выполните команду:
Invoke-Command –computername ONE,TWO,THREE –scriptblock { Get-EventLog Security –newest 100 } | Export-CliXML results.xml
При выполнении на удаленном компьютере целого сценария, он обычно генерирует в качестве результат объекты (желательно, чтобы это были объекты одного типа). В частности, следующий сценарий предназначается для пересылки на удаленный компьютер через параметр –FilePath командлета Invoke-Command. Обратите внимание, что он создает новый объект и размещает в нем информацию из двух локальных объектов. Готовый объект передается в конвейер, который перенаправляется на компьютер, где была выполнена команда Invoke-Command:
$os = Get-WmiObject –class Win32_OperatingSystem
$bios = Get-WmiObject –class Win32_BIOS
$obj = New-Object –TypeNamePSObject
$obj | Add-Member NotePropertyOSVersion $os.caption
$obj | Add-Member NotePropertyBIOSSerial $bios.serialnumber
Write-Output $obj
Автоматически добавляется свойство PSComputerName, поэтому не составляет труда узнать, с какого компьютера поступил тот или иной результат. Подобное возвращение объектов одного типа наилучшим образом согласуется с другими возможностями оболочки, поэтому его определенно можно рекомендовать в качестве механизма получения выходных данных из удаленно выполняемого сценария.