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 enumerate: проверить листенер

В данном случае служба 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.

Enable-PSRemoting включить и настроить winrm в Windows

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

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

Test-WsMan compname1

Test-WsMan - проверить работу winrm на удаленном компьютере

По умолчанию 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:\localhost\Client\TrustedHosts -value 192.168.1.201
Либо можно разрешить подключение ко все компьютерам (не рекомендуется, т.к. один из главных недостатков NTLM – он не осуществляет проверку подлинности)
Set-Item wsman:\localhost\Client\TrustedHosts -value *

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

Restart-Service WinRM

Set-Item wsman:\localhost\Client\TrustedHosts


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

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

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

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

Invoke-Command удаленно запустить команду

Чтобы прервать удаленный запуск команды через 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 несколько команд в блоке ScriptBlock

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

Invoke-Command -ComputerName Server01 -FilePath c:\PS\Scripts\GetComputerInfo.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}

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

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

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

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

Invoke-Command -ScriptBlock {Restart-Service spooler} -ComputerName(Get-Content c:\ps\servers.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 вернуть результы с каждого компьютера через PSComputerName

В 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 }
запуск invoke-command в persistent powershell pssession

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

Remove-PSSession $s


Предыдущая статья Следующая статья


Комментариев: 24 Оставить комментарий

Оставить комментарий

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

Я не робот( Обязательно отметьте)