Invoke-Command: запуск команды/скрипта на удаленном компьютере

Для удаленного запуска команд или PowerShell скриптов на одном или нескольких удаленных компьютерах можно использовать командлет Invoke-Command.

Настройка WinRM для PowerShell Remoting

Для установки связи с удаленным компьютерами командлет Invoke-Command использует сессии PowerShell Remoting. Технология удаленного управления и запуска команд PowerShell Remoting основана на протоколе WS-Management (реализуется через службу WinRM, Windows Remote Management). Для связи с удаленным компьютерами используются протокол HTTP (порт TCP/5985 ) или HTTPS (порт TCP/5986 ). По умолчанию используется протокол HTTP, но даже этот трафик шифруется с помощью ключа AES-256 (впрочем, есть угроза атак man-in-the middle). Возможна аутентификация через Kerberos (в домене) или NTLM.

Чтобы установить сессию (PSSession) с удаленным компьютерам, на нем нужно включить службу WinRM и разрешить удаленные подключения:

Проверьте, что на клиенте запущена служба WinRM и слушатель службы (WinRM listener):

Get-Service -Name "*WinRM*" | fl
WinRM enumerate winrm/config/listener

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

winrm quickconfig

или

Enable-PSRemoting -Force

WinRM has been updated to receive requests. WinRM service started. 
WinRM is already set up for remote management on this computer.

Эта команда запустит службу WinRM (установит автоматический запуск), задаст настройки winrm по-умолчанию и добавит исключения в Windows Firewall.

Теперь проверьте возможно ли удаленное подключение к компьютеру через PSRemoting:

Test-WsMan compname1

По умолчанию WinRM не будет работать для сетевых подключений, которые определяются как общедоступные (Public). Рекомендуется изменить тип сети в Windows на частную (private) или доменную. Если это невозможно, можно разрешить WinRM для общедоступных сетей и включить соответствующее правило брандмауэра:
Enable-PSRemoting -SkipNetworkProfileCheck
Set-NetFirewallRule -Name 'WINRM-HTTP-In-TCP' -RemoteAddress Any

Если компьютеры не в домене (используется рабочая группа), или вы обращаетесь к компьютерам через по IP адресам, в этом случае для аутентификации вместо Kerberos использоваться протокол NTLM. Чтобы разрешить NTLM аутентификацию через WimRM, нужно на компьютере (с которого вы будете устанавливать подключения) добавить имя/IP удаленного хоста в доверенные:
Set-Item wsman:localhostClientTrustedHosts -value 192.168.1.201
Либо можно разрешить подключение ко все компьютерам (не рекомендуется, т.к. один из главных недостатков NTLM – он не осуществляет проверку подлинности)
Set-Item wsman:localhostClientTrustedHosts -value *

Аналогичные настройки нужно сделать на удаленных хостах.
Чтобы вывести список доверенных хостов, выполните команду:
Get-Item WSMan:localhostClientTrustedHosts
Чтобы применить изменения, перезапустите службу WinRM:

Restart-Service WinRM

Выполнение удаленных команд через Invoke-Command

Чтобы выполнить одну команду на удаленном компьютере, нужно указать имя компьютера ( -ComputerName ) и саму команду в блоке {ScriptBlock} :

Invoke-Command -ComputerName dc01 -ScriptBlock {$PSVersionTable.PSVersion}

Командлет отправит указанную команду на удаленный компьютер и выведет результат в консоль (результат возвращается в виде объекта PowerShell). В данном случае мы проверили состояние службы Windows Update на удаленном компьютере.

Чтобы прервать удаленный запуск команды через Invoke-Command, нажмите в консоли CTRL+C .

Командлет Invoke-Command выполняет команды от имени пользователя, под которым запущена консоль PowerShell. Чтобы выполнить команду от другого пользователя, используется параметр -Credential :

$cred = Get-Credential
Invoke-Command -ComputerName comp-buh2 -Credential $cred -ScriptBlock {Get-NetAdapter}

Эта PowerShell команда выведет список сетевых интерфейсов на удаленном компьютере:

  • Право на удаленное подключение через PSRemoting есть у членов группы локальных администраторов и Remote Management Users.
  • Если в отправляемой на удаленный компьютер команде есть обращение к удаленному ресурсу (например папке сетевой папке), при аутентфикации на втором ресурсе произойдёт ошибка. Эта проблема называется double hop (двойной прыжок) и связана с ограничениями безопасности Windows, запрещающими передачу учетных данных на третий ресурс.

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

Invoke-Command -Computername dc01 -ScriptBlock {Get-TimeZone| select DisplayName;Set-TimeZone -Name "Astrakhan Standard Time"}

Командлет Invoke-Command позволяет запускать не только отдельные команды, но и скрипты PowerShell. Для этого нужно указать путь к локальному PS1 файлу со скриптом в параметре -FilePath :

Invoke-Command -ComputerName Server01 -FilePath c:PSScriptsGetComputerInfo.ps1

Если нужно передать значение локальной переменной из скрипта в блок команд Invoke-Command, используется конструкцию $using :

$localVar = Get-Date
Invoke-Command -ComputerName Server01 -ScriptBlock {
"Date = $using:localVar"
}

Invoke-Command: одновременный запуск команд на нескольких компьютерах

Командлет Invoke-Command позволяет выполнить вашу команду одновременно (параллельного) на нескольких удаленных компьютерах. В самом просто случае имена компьютеров, на которых нужно выполнить команды указываются через запятую:

Invoke-Command server1, server2, server3 -ScriptBlock {get-date}

Список компьютеров можно поместить в переменную (массив):

$servers = @("server1","server2","server3")
Invoke-Command -ScriptBlock { get-date} -ComputerName $servers

Или получить из текстового файла:

Invoke-Command -ScriptBlock {Restart-Service spooler} -ComputerName(Get-Content c:psservers.txt)

Также можно получить список компьютеров в ADс помощью командлета Get-ADComputer из модуля AD PowerShell. Например, чтобы выполнить команду на всех Windows Server в домене, используйте такой код:

$computers = (Get-ADComputer -Filter 'operatingsystem -like "*Windows server*" -and enabled -eq "true"').Name
Invoke-Command -ComputerName $computers -ScriptBlock {get-date} -ErrorAction SilentlyContinue

Если компьютер выключен, или недоступен, благодаря параметру SilentlyContinue скрипт не будет остановлен и продолжит выполнение на других компьютерах.

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

$results = Invoke-Command server1, server2, server3 -ScriptBlock {get-date}
$results | Select-Object PSComputerName, DateTime

В Invoke-Command есть ограничение на максимальное количество одновременных сессий с компьютерами. По умолчанию она равно 32 (определяется параметром ThrottleLimit. Если вам нужно выполнить команду одновременно более чем на 32 компьютерах (например, на 128), используйте параметр –ThrottleLimit 128 .

Для запуска команд на удаленных компьютерах через Invoke-Command в фоновом режиме используется специальный атрибут –AsJob . В этом случае результат выполнения команды не возвращается в консоль. Чтобы получить результаты нужно использовать командлет Receive-Job .

Для интерактивного запуска команды на удаленном компьютере, используйте командлет Enter-PSSession.

Постоянные сессии в PowerShell Remoting

Если вам часто нужно выполнять команды на удаленном компьютер, можно создать постоянную PSRemoting сессию с удаленным компьютером. В этом случае командлету Invoke-Command не нужно будет каждый раз инициировать удаленное подключение.

Создадим постоянную (persistent) сессию с удаленным одним или несколькими компьютерами:

$s = New-PSSession -ComputerName Server01, Server02

Теперь, чтобы выполнить команду в созданном сеансе PSSession, используйте параметр -Session:

Invoke-Command -Session $s -ScriptBlock { Get-ComputerInfo|select OsLastBootUpTime }

Чтобы закрыть удаленную сессию, нужно закрыть консоль PowerShell или выполнить:

Remove-PSSession $s


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *