Запустите интерактивный «главный» сценарий PowerShell на локальном ПК, а также на удаленных ПК и войдите в журнал.

У меня есть массивный (983 строки) интерактивный сценарий PowerShell, который я написал для управления практически всеми аспектами локального сервера. У меня есть текстовый файл со списком серверов. Я хочу сойти с ума от этого.

Содержимое текстового файла:

Server1Name
Server2Name

Интерактивное меню PowerShell:

Write-Host "Welcome to the environment control script."
Write-Host " "
Write-Host "What would you like to do? Select the number:"
Write-Host "========================================================================="
Write-Host "1. Create a backup of the environment (existing servers)"
Write-Host "2. Backup environment and deploy updated environment (existing servers)"
Write-Host "3. Deploy new environment including IIS (clean servers)"
Write-Host "4. Deploy just IIS (clean servers)"
Write-Host "5. Remove Build w/ backup and cleanup IIS (existing servers)"
Write-Host "6. Remove Build w/out backup and cleanup IIS (existing servers)"
Write-Host "7. Remove and cleanup only IIS (existing servers)"
Write-Host "8. Deploy new DLL's (existing servers)"
Write-Host "9. [EXIT]" -foregroundcolor "yellow"
Write-Host " "

Цель:

Попытка избежать 1000 пакетных файлов на моих серверах

Пример:

Я запускаю скрипт на «главном» сервере, а в текстовом файле есть еще 10 серверов. Сначала скрипт работает ТОЛЬКО на главном сервере. Как только я выбираю вариант 6, запускается команда для выполнения одних и тех же команд на всех 11 серверах (главный + 10 других).

Я знаю, как запустить один и тот же скрипт на разных серверах, если это, скажем, простая копия файла или сброс службы (без взаимодействия с пользователем) с использованием таких вещей, как invoke-command или enter-pssession и т. д.... однако в моем случае мне придется удаленно на каждый сервер, потому что он интерактивный... если нет способа сделать это?

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

Любая помощь будет оценена по достоинству.

Обновление: 08.03.16

Итак, @Cobster помог мне, и мы готовы на 99%.

Используя следующий код, похоже, что скрипт пытается запуститься, однако есть еще одна проблема.

$sessions = New-PSSession -ComputerName $servers 
$job = Invoke-Command -Session $sessions -ScriptBlock ${function:Backup} -AsJob

If you want a different job for each machine, you can do the following:

$jobs = $sessions | ForEach-Object { Invoke-Command -Session $_ -ScriptBlock ${function:Backup} -AsJob } 
Wait-Job -Job $jobs

Проблема в том, что когда это сделано, команда invoke, похоже, не импортирует все мои ранее объявленные переменные в верхней части моего скрипта (который включает практически ВСЕ мои пути и т. д., потому что они не определены в этой функции .

Это приводит к множеству следующих типов ошибок (точнее, 7, по одной на каждую проверку моего тестового пути перед выполнением шага):

Cannot bind argument to parameter 'Path' because it is null.
    + CategoryInfo          : InvalidData: (:) [Test-Path], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.TestPathCommand
    + PSComputerName        : *ServerName*

Решение:

Используйте -ArgumentList $variable1, $variable2 в invoke-command и

param ( $variable1, $variable2 ) внутри функции... любезно предоставлено Cobster.


person Ilya    schedule 16.02.2016    source источник
comment
Обновлен основной пост, с помощью одного из участников удалось проработать большую часть этого, но столкнулись, казалось бы, с одним последним препятствием.   -  person Ilya    schedule 08.03.2016


Ответы (1)


Invoke-Command можно запустить в фоновом режиме с помощью переключателя -AsJob.

Ведение журнала также возможно с помощью командлета Receive-Job для получения выходных данных каждого из фоновых заданий после их завершения.

person Cobster    schedule 16.02.2016
comment
Спасибо @Кобстер. Наконец-то я попробовал это (временно был переведен в другой проект). Когда я запускаю следующую команду, похоже, она ничего не делает. Это не ошибка, но, например, на самом деле не работает функция резервного копирования. Invoke-Command -ComputerName $Servers -ScriptBlock ${функция:Резервное копирование} -AsJob - person Ilya; 02.03.2016
comment
Есть ли какие-либо выходные данные или ошибки, когда Receive-Job вызывается для этих заданий? - person Cobster; 02.03.2016
comment
Я выполнил следующее из своего главного сценария @Cobster... Я выбрал вариант 1 (для создания резервной копии). $s = New-PSSession -ComputerName $Servers, затем $j = Invoke-Command -Session $s -ScriptBlock {Start-Job -ScriptBlock ${function:Backup}}, затем $j, а затем $results = Invoke-Command -Session $s -ScriptBlock {param($j) Recieve-Job -Job $j} -ArgumentList $j. Я получил сообщение об ошибке: Невозможно связать аргумент с параметром 'ScriptBlock', поскольку он равен нулю. Это появилось дважды, после чего появились сообщения о том, что 'Recieve-Job' не является допустимым командлетом для каждого сервера (всего 2 прямо сейчас) - person Ilya; 03.03.2016
comment
Ах, проблема с блоком сценария ${function:Backup}. Вам нужно передать это как переменную в блок сценария Invoke-Command. Invoke-Command -Session $s -ScriptBlock { param ($s) Start-Job -ScriptBlock $s } -ArgumentList ${function:Backup} - person Cobster; 03.03.2016
comment
Хм... в этом есть смысл @Cobster. Я изменил его и получил два сообщения (для каждого сервера), говорящие cannot bind parameter 'ScriptBlock'. Cannot convert the value **prints out my whole function here** of type 'System.String' to type "System.Management.Automation.ScriptBlock'... Также есть две ошибки получения задания, которые были раньше. - person Ilya; 03.03.2016
comment
Итак, проблема в том, что переменная должна быть блоком скрипта. ${function:[name]} — строковая версия функции. Возможно, -ArgumentList { &${function:Backup} } сработает. Это создает блок скрипта-оболочки и вызывает строку с &. - person Cobster; 03.03.2016
comment
На этот раз он не перечислил всю мою функцию, но выдал почти ту же ошибку. @Кобстер - person Ilya; 03.03.2016
comment
Возможно, блок сценария не может быть маршаллирован с помощью удаленного взаимодействия. Попробуйте следующее Invoke-Command -Session $s -ScriptBlock { param ($s) Start-Job -ScriptBlock { & $s } } -ArgumentList ${function:Backup}. Если это не сработает, попробуйте { iex $s } - person Cobster; 03.03.2016
comment
Хорошо, так что это не привело к ошибкам (хотя ошибка командлета по-прежнему недействительна). Однако на самом деле он не запускал мою функцию резервного копирования. Я попробовал оба варианта вашего последнего предложения. Как будто теперь он видит функцию, но на самом деле никогда не входит в нее, поскольку даже не распечатал некоторые из Write-Hosts, которые у меня есть... @Cobster - person Ilya; 03.03.2016
comment
Звучит как прогресс. Итак, я предполагаю, что скрипт теперь загружен в контексте, вы сможете вызвать его, вызвав функцию. -ScriptBock { & $s; Backup } - person Cobster; 03.03.2016
comment
Как только я исправил ScriptBock на ScriptBlock :P... Я получил следующее The expression after '&' in a pipeline element produced a object that was not valid. It must result in a command name, script block or CommandInfo object. Получил это дважды, а также одно сообщение о том, что имя моей функции Backup не является допустимым командлетом @Cobster. Определенно прогресс, я ценю вашу помощь! - person Ilya; 03.03.2016
comment
Давайте продолжим обсуждение в чате. - person Cobster; 03.03.2016
comment
Добавил в обсуждение. - person Cobster; 04.03.2016
comment
Я обновил основной пост @Cobster... Кажется, я нашел последнее препятствие, просто не знаю, как его преодолеть. - person Ilya; 08.03.2016
comment
Привет, @Cobster... столкнулся с небольшой проблемой. Пожалуйста, проверьте чат, когда у вас будет минутка. - person Ilya; 15.03.2016