Существует довольно много методов для работы с удаленными компьютерами. Есть Windows Management Instrumentation (WMI), широко используемый в VBScript. Есть различные утилиты, которые позволяют осуществлять удаленное управление, типа PSExec от Sysinternals. Даже многие командлеты PowerShell имеют параметр ComputerName для выполнения на удаленных компьютерах.
В общем методов полно, но у каждого из них есть свои минусы. Во первых — разный синтаксис, в котором легко запутаться. Во вторых — некоторые команды ведут себя по разному в зависимости от того, локально или удаленно они выполняются. Ну и наконец, для связи может потребоваться открытие дополнительных портов на брандмауэре, что не есть хорошо с точки зрения безопасности.
PowerShell Remoting решает большинство описанных проблем. Он основан на Microsoft реализации протокола Web Services for Management (WS-Management), а для связи использует службу Windows Remote Management (WinRM). Связь между компьютерами осуществляется по HTTP (по умолчанию) или HTTPS. Весь трафик между двумя компьютерами шифруется на уровне протокола (за исключением случаев, когда используется SSL). Поддерживаются несколько методов аутентификации, включая NTLM и Kerberos.
В отличие от утилит, использующих различные программные интерфейсы, PS Remoting работает следующим образом: команды, вводимые на локальном компьютере, передаются на удаленный компьютер и там выполняются, затем результат передается обратно. Поскольку все команды выполняются локально, нет необходимости заботится о совместимости. Кроме того, для работы PS Remoting нужен всего один открытый порт на брандмауэре.
Есть несколько способов управления с помощью PowerShell Remoting.
Управление «один к одному»
Самый простой способ удаленного управления — интерактивно открыть удаленную сессию и в ней выполнить нужные действия. Например, откроем сессию на компьютер SRV4 и рестартуем на нем сервис печати:
Enter-PSSession -ComputerName SRV4
Restart-Service -Name spooler
Посмотрим состояние сервиса и закроем удаленную сессию:
Get-Service -Name spooler
Exit-PSSession
Интерактивная работа подходит для решения несложных задач удаленного администрирования. Если же надо автоматизировать процесс, то лучше воспользоваться командлетом Invoke-Command. Вот так с его помощью можно сделать то же самое действие:
Invoke-Command -ScriptBlock {Restart-Service spooler} -ComputerName SRV4
Эта команда откроет удаленную сессию на SRV4, выполнит блок команд, указанный в параметре -ScriptBlock, и закроет сессию. А чтобы задание выполнялось в фоновом режиме, дополнительно можно указать параметр -AsJob.
Cледует помнить о том, что при работе в фоновом режиме PowerShell не возвращает результат. Для его получения придется воспользоваться командлетом Receive-Job.
Для того, чтобы выполнить не пару-тройку команд, а какой либо скрипт, у Invoke-Command есть параметр –FilePath, который можно использовать вместо –ScriptBlock для определения файла сценария. Для примера я создал скрипт, который выводит список остановленных служб и запустил его на удаленной машине SRV4:
Invoke-Command -FilePath .\script.ps1 -ComputerName SRV4
Управление «один ко многим»
Довольно часть возникает необходимость параллельно выполнить одну задачу на нескольких компьютерах. Это довольно легко можно сделать с помощью того же Invoke-Command. Например, имена компьютеров можно просто перечислить через запятую:
Invoke-Command -ScriptBlock {Restart-Service spooler} -ComputerName SRV4,SRV5
Поместить в переменную:
$servers = @(″SRV1″,″SRV2″,″SRV3″)
Invoke-Command -ScriptBlock {Restart-Service spooler} -ComputerName $servers
Или взять из файла:
Invoke-Command -ScriptBlock {Restart-Service spooler} -ComputerName`
(Get-Content .\servers.txt)
Примечание: у Invoke-Command есть параметр ThrottleLimit, ограничивающий максимальное количество компьютеров, которыми можно управлять одновременно. По умолчанию этот параметр равен 32. При необходимости его можно изменить, но учтите, что повышение этого параметра увеличит нагрузку на процессор и память вашего компьютера, поэтому эту операцию нужно выполнять с большой осторожностью.
Сессии
Каждый раз при выполнении Invoke-Command создается новая сессия, на создание которой тратится время и ресурсы. Чтобы этого избежать мы можем открыть одну сессию, в которой и выполнять все команды. Например, откроем сессию с именем SRV4 на компьютер SRV4 и поместим ее в переменную $session, а затем этой сессии выполним нашу задачу (остановим многострадальный spooler):
$session = New-PSSession -ComputerName SRV4 -Name SRV4
Invoke-Command -ScriptBlock {Get-Service spooler | Stop-Service}`
-Session $session
Сессия будет активна до того момента, пока мы не выйдем из консоли PowerShell. Также сессию можно закрыть — Disconnect-PSSession или удалить — Remove-PSSession.
А теперь несколько интересных возможностей, появившихся в PowerShell 3.0. Если раньше при выходе из сессии или закрытии консоли сессия удалялась, то в PS 3.0 при закрытии сессия переходит в состояние disconnected. Мы можем открыть новый сеанс на этом же (или любом другом) компьютере и выполнить команду прямо в этой отключенной сессии. В качестве примера стартуем на компьютере SRV4 сервис печати, остановленный в прошлый раз:
Invoke-Command -ScriptBlock {Start-Service spooler}`
-ComputerName SRV4 -Disconnected
Еще один вариант использования отключенных сессий — запуск длительных по времени задач. Для примера откроем сессию c именем LongJob на SRV4 и запустим в ней фоновое задание, которое будет выводить список сервисов с интервалом в 1 минуту:
$session = New-PSSession -ComputerName SRV4 -Name LongJob
Invoke-Command -Session $session -ScriptBlock`
{Get-Service | foreach {$_;sleep 60} } -AsJob
Посмотрим, как выполняется задача и закроем сессию:
Receive-Job -Name Job2
Disconnect-PSSession $session
Идем на другой компьютер и открываем консоль, Подключаемся к сессии LongJob и с помощью командлета Receive-PSSession получаем результат выполнения задания:
Connect-PSSession -Name LongJob -ComputerName SRV4
Receive-PSSession -Name LongJob
Или еще вариант, без явного подключения к сессии с помощью Connect-PSSession:
$session = Get-PSSession -Name LongJob -ComputerName SRV4
$job = Receive-PSSession $session -OutTarget Job
Receive-Job $job
Примечание: для того, чтобы результат остался в системе, Receive-Job надо использовать с параметром -Keep.
Неявное удаленное управление
Еще один, довольно нестандартный способ удаленного управления — неявное удаленное управление (Implicit remoting). Используя его можно, не создавая удаленной сессии, локально выполнять командлеты, находящиеся на удаленном компьютере.
Для примера берем обычную рабочую станцию, без установленных средств удаленного администрирования. Создаем удаленную сессию с контроллером домена SRV4 и импортируем в эту сессию модуль Active Directory:
$session = New-PSSession -ComputerName SRV4
Invoke-Command {Import-Module ActiveDirectory} -Session $session
Затем экспортируем из удаленной сессии командлеты Active Directory и помещаем их в локальный модуль RemoteAD:
Export-PSSession -Session $session -CommandName *-AD* -OutputModule RemoteAD`
-AllowClobber
Эта команда создаст в папке WindowsPowerShell\Modules\RemoteAD новый модуль PowerShell. Загружены будут только командлеты с именами, соответствующими шаблону *-AD*. При этом сами командлеты не копируются на локальный компьютер. Локальный модуль служит своего рода ярлыком, а сами команды будут выполняться на удаленном контроллере домена.
После создания модуля удаленную сессию можно закрыть, она больше не понадобится.
Импортируем новый модуль в текущий сеанс (в PS 3.0 можно этот шаг пропустить):
Import-Module RemoteAD
А теперь внимание — мы не открываем удаленную сессию с контроллером домена, где расположены командлеты. Не нужно явно запускать этот сеанс — это можно сделать неявно, попытавшись выполнить удаленные командлеты:
New-ADUser -Name BillGates -Company Microsoft
Get-ADUser BillGates
При этом будет восстановлено удаленное подключение к контроллеру домена, после чего команда будет передана на контроллер домена и там выполнена. Результат выполнения будет сериализован в XML и передан по сети на локальный компьютер, где будет выполнена десериализация в объекты, с которыми может работать PowerShell.
Удаленный сеанс будет активным до тех пор, пока вы не закроете консоль или не удалите модуль RemoteAD.
Неявное удаленное управление позволяет работать с командлетами на удаленном компьютере практически так же, как если бы они были установлены на локальной машине. При этом все необходимые командлеты всегда под рукой, что довольно удобно.
В заключение скажу, что на данный момент PowerShell Remoting является основным инструментом для удаленного управления операционными системами Windows. Поэтому знать о его возможностях и уметь ими пользоваться просто необходимо любому Windows-администратору.
А почему появляются «кракозябры» при выдаче в консоли Enter-PSSession? К примеру, вывод команды ipconfig.
P. S. Поправьте опечатку, пожалуйста: «приЙдется воспользоваться командлетом Receive-Job»