У меня есть сценарий powershell, который запускается для подключения к удаленным серверам и выполнения сценария. Я также передаю аргумент. Есть ли способ запустить это параллельно, передавая правильные идентификаторы, отвечающие каждому STORES. Версия powershell 5 в системе.
$storeids = Get-Content 'D:\StoreMap.json' -Raw | ConvertFrom-Json
$storeids | Select-Object -Property STORE, ID | ForEach-Object {
$computer = 'IN' + $_.STORE + 'test.org'
$ID = $_.ID
$script = 'D:\test.ps1'
Write-Host "Started running the script on Store" + $computer
try {
Invoke-Command -ComputerName $computer -FilePath $script -ArgumentList $ID
}
catch {
Write-Host $_.Exception.Message
}
}
Вы можете запускать каждый компьютер как задание — Start-Job
затем использовать цикл, чтобы проверить, когда завершатся полученные задания, и получить результаты. Я делаю это, чтобы запрашивать все журналы событий контроллера домена параллельно.
invoke-command computer1,computer2,computer3 script.ps1
Команда вызова @JeffZeitlin выполняется параллельно с массивом имен компьютеров.
Но мне нужно было бы передать относительный аргумент для каждого компьютера. Так что для компьютера1 мне нужно будет передать его относительный ID1, для компьютера2, ID2 и т.д.
Как в итоге выглядит 'IN' + $_.STORE + 'test.org'
? Не хватает точек?
Он заканчивается как «IN1111test.org», STORE — это 4-значное целое число.
я бы предложил это
Get-Content 'D:\StoreMap.json' -Raw |
ConvertFrom-Json |
Select-Object -Property STORE, ID |
ForEach-Object {
$computer = 'IN'+$_.STORE+'test.org'
$ID= $_.ID
Write-Host "Started running the script on Store " + $computer
$ScriptBlock = {
Param([string] $ID)
#Your remote code here, most likely content of D:\test.ps1
}
Start-Job -Name "Script on $($computer)" -ScriptBlock $ScriptBlock -Args $ID
}
Get-Job | Wait-Job
$return += Get-Job | Receive-Job
Это дает следующее: Значения поставки для следующих параметров процесса 0
Что именно требует аргумента?
Итак, я передаю аргумент/параметр $ID в «содержимое D:\test.ps1». Когда я помещаю фактический код test.ps1, как вы просили, когда я пытаюсь его запустить, он дает мне : Предоставление значений для следующих параметров процесса 0
Вы можете создать хеш-таблицу для поиска идентификатора на основе имени удаленного компьютера, а затем вызывать их параллельно с помощью Invoke-Command
.
Две вещи на заметку
также см. встроенные комментарии для деталей.
$storeids = Get-Content 'D:\StoreMap.json' -Raw | ConvertFrom-Json
# The assumption is IN + $_.Store is exactly the remote systems computer name, stored as Hostname property
# The ComputerName property is the fqdn for the Invoke-Command call
$selectprops = '*',
@{n='Hostname';e = {"IN$($_.Store)"}},
@{n='ComputerName';e = {"IN$($_.Store)test.org"}}
# Create a lookup table. Each remote system will be able to extract their own ID from this table via it's computername
$storetable = $storeids |
Select-Object $selectprops |
Group-Object -Property Hostname -AsHashTable
# Instead of using a passed in argument, use $using:storetable to grab a local copy of the table and then
# reference it with $localtable[$env:computername]
# Silence errors to prevent interruption and capture any errors to $errors (appended due to +)
$icmparams = @{
ComputerName = $storetable.Name
FilePath = 'D:\test.ps1'
ErrorAction = 'SilentlyContinue'
ErrorVariable = '+errors'
ThrottleLimit = 64 # 32 by default
}
$results = Invoke-Command @icmparams
# output collected in $results
$results
# check any errors
$errors
<# D:\test.ps1
$localtable = $using:storetable
$id = $localtable[$env:computername].ID
"Computer: $env:Computername ID: $id"
#>
Эй, Дуг, большое спасибо, что уделили этому время. Здесь «selectprops» хранит все магазины, сопоставленные в файле json? Я попытался проверить WriteHost, но, похоже, он ничего не печатает.
Он берет все свойства из $storeid и добавляет два дополнительных свойства. $selectprops = '*', @{n='Hostname';e = {"IN$($_.Store)"}}, @{n='ComputerName';e = {"IN$($_.Store)test.org"}}
Я чувствую, что я действительно плох в этом, но ComputerName = $storetable.ComputerName, это кажется нулевым или пустым. Я попытался напечатать $storetable.values, и он распечатывается нормально, а $storetable.ComputerName — нет.
Ты прав. Это должно быть $storetable.Name
Возможно, вы захотите изучить модуль PSPallel. Windows Powershell (версия 5.x или более ранняя) не имеет встроенных возможностей параллельного выполнения.