Вопрос по – Переменные в Start-Job

2

У меня есть этот код PowerShell, который я хотел бы заставить работать. В настоящее время он не оценивает переменную $ agent.

<code>foreach($agent in $agentcomputers){
Write-Output 'Starting agent on '$agent
#psexc to start the agent
Start-Job -ScriptBlock {& psexec $agent c:\grinder\examples\startAgent.cmd}
}
</code>

Это похоже на мою проблему, за исключением того, что я не вызываю внешний сценарий powershell.

https://sqlblog.org/2011/01/29/powershell-start-job-scriptblock-sad-panda-face

Я попытался добавить это, используя $ args [0] для $ agent и добавив параметры -ArgumentList, но это не сработало.

Спасибо за любую помощь, которую вы можете предоставить.

Edits/Replys...

Это $ agentcomputers, просто список имен компьютеров. Каждый на своей собственной линии.

<code>$agentcomputers = Get-Content c:\grinder-dist\agent-computers.txt
</code>

Я также попробовал это - и $ args [0] не оценивает

<code>Start-Job -ScriptBlock {& psexec $args[0] c:\grinder\examples\startAgent.cmd} -ArgumentList @($agent)
</code>
Что хранится в$agent? Andy Arismendi
Возможно, вам понадобится обратная косая черта в соответствии с psexecdocumentation "\\$args[0]", Убедитесь, что команда работает сама по себе без фонового задания. Andy Arismendi
@DavidBrabant глобальная область не будет работать, так как она выполняется в отдельном процессе PowerShell.exe. Данные сериализуются и передаются в фоновый процесс. Andy Arismendi
Вы также можете изменить область действия переменной $ agent, я думаю: $ global: agent. David Brabant
Вам нужно будет использовать параметр ArgumentList либо используя$args массив или блок параметров. Andy Arismendi

Ваш Ответ

2   ответа
4

мне нужно было использовать массив $ args с параметром -ArgumentList. Эта другая тема была полезна:Powershell: передача параметров на работу

foreach($agent in $agentcomputers){
$agentslash = "\\"+$agent
$args = ($agentslash,"c:\grinder\examples\startAgent.cmd")
Write-Output 'Starting agent on '$agent

#psexc to start the agent
$ScriptBlock = {& 'psexec' @args } 

Start-Job -ScriptBlock $ScriptBlock -ArgumentList $args

}
9

Во-первых, все ровно и красиво.

$agents = Get-Content c:\grinder-dist\agent-computers.txt
$jobs = {
     Param($agent)
         write-host "Starting agent on" $agent
         & psexec \\$agent c:\grinder\examples\startAgent.cmd
}
foreach($agent in $agents) {
     Start-Job -ScriptBlock $jobs -argumentlist $agent | Out-Null
}
Get-Job | Wait-Job | Receive-Job

Или вы можете просто поместить все это в одну строку, не создавая никаких переменных.

(Get-Content c:\grinder-dist\agent-computers.txt) | %{ Start-Job -ScriptBlock { param($_) write-host "Starting agent on" $_; & psexec \\$_ c:\grinder\examples\startAgent.cmd } -argumentlist $_ | Out-Null }
Get-Job | Wait-Job | Receive-Job

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

$MaxThreads = 5
$agents = Get-Content c:\grinder-dist\agent-computers.txt
$jobs = {
     Param($agent)
         write-host "Starting agent on" $agent
         & psexec \\$agent c:\grinder\examples\startAgent.cmd
}
foreach($agent in $agents) {
     Start-Job -ScriptBlock $jobs -argumentlist $agent | Out-Null
     While($(Get-Job -State 'Running').Count -ge $MaxThreads) {
          sleep 10
     }
     Get-Job | Wait-Job | Receive-Job
} 

Похожие вопросы