Powershell 使用运行空间而不是foreach循环的多线程
我有一个带有foreach循环的脚本。它有十几个功能,每个功能都从远程机器的C$共享中收集信息(剪切文本文件、检查文件版本等) 然而,这需要一些时间,因为每台机器的数据都是在一个接一个地收集之后收集的。(有时它以500+输入运行) 我们希望将其放入并行执行的运行空间中,但到目前为止,还没有任何示例起作用。我对这个概念很陌生 当前脚本的大纲 $inputfile=c:\temp\computerlist.txt 职能1 职能2 职能3等 foreach循环 职能1 职能2 职能3Powershell 使用运行空间而不是foreach循环的多线程,powershell,foreach,parallel-processing,Powershell,Foreach,Parallel Processing,我有一个带有foreach循环的脚本。它有十几个功能,每个功能都从远程机器的C$共享中收集信息(剪切文本文件、检查文件版本等) 然而,这需要一些时间,因为每台机器的数据都是在一个接一个地收集之后收集的。(有时它以500+输入运行) 我们希望将其放入并行执行的运行空间中,但到目前为止,还没有任何示例起作用。我对这个概念很陌生 当前脚本的大纲 $inputfile=c:\temp\computerlist.txt 职能1 职能2 职能3等 foreach循环 职能1 职能2 职能3 现在,所有结果都
现在,所有结果都将通过write host写入屏幕。此示例并行ping多个服务器,因此您可以根据需要轻松修改它:
Add-Type -AssemblyName System.Collections
$GH = [hashtable]::Synchronized(@{})
[System.Collections.Generic.List[PSObject]]$GH.results = @()
[System.Collections.Generic.List[string]]$GH.servers = @('server1','server2','server3');
[System.Collections.Generic.List[string]]$GH.functions = @('Check-Server');
[System.Collections.Generic.List[PSObject]]$jobs = @()
#-----------------------------------------------------------------
function Check-Server {
#-----------------------------------------------------------------
# a function which runs parallel
param(
[string]$server
)
$result = Test-Connection $server -Count 1 -Quiet
$GH.results.Add( [PSObject]@{ 'Server' = $server; 'Result' = $result } )
}
#-----------------------------------------------------------------
function Create-InitialSessionState {
#-----------------------------------------------------------------
param(
[System.Collections.Generic.List[string]]$functionNameList
)
# Setting up an initial session state object
$initialSessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
foreach( $functionName in $functionNameList ) {
# Getting the function definition for the functions to add
$functionDefinition = Get-Content function:\$functionName
$functionEntry = New-Object System.Management.Automation.Runspaces.SessionStateFunctionEntry -ArgumentList $functionName, $functionDefinition
# And add it to the iss object
[void]$initialSessionState.Commands.Add($functionEntry)
}
return $initialSessionState
}
#-----------------------------------------------------------------
function Create-RunspacePool {
#-----------------------------------------------------------------
param(
[InitialSessionState]$initialSessionState
)
$runspacePool = [RunspaceFactory]::CreateRunspacePool(1, ([int]$env:NUMBER_OF_PROCESSORS + 1), $initialSessionState, $Host)
$runspacePool.ApartmentState = 'MTA'
$runspacePool.ThreadOptions = "ReuseThread"
[void]$runspacePool.Open()
return $runspacePool
}
#-----------------------------------------------------------------
function Release-Runspaces {
#-----------------------------------------------------------------
$runspaces = Get-Runspace | Where { $_.Id -gt 1 }
foreach( $runspace in $runspaces ) {
try{
[void]$runspace.Close()
[void]$runspace.Dispose()
}
catch {
}
}
}
$initialSessionState = Create-InitialSessionState -functionNameList $GH.functions
$runspacePool = Create-RunspacePool -initialSessionState $initialSessionState
foreach ($server in $GH.servers)
{
Write-Host $server
$job = [System.Management.Automation.PowerShell]::Create($initialSessionState)
$job.RunspacePool = $runspacePool
$scriptBlock = { param ( [hashtable]$GH, [string]$server ); Check-Server -server $server }
[void]$job.AddScript( $scriptBlock ).AddArgument( $GH ).AddArgument( $server )
$jobs += New-Object PSObject -Property @{
RunNum = $jobCounter++
JobObj = $job
Result = $job.BeginInvoke() }
do {
Sleep -Seconds 1
} while( $runspacePool.GetAvailableRunspaces() -lt 1 )
}
Do {
Sleep -Seconds 1
} While( $jobs.Result.IsCompleted -contains $false)
$GH.results
Release-Runspaces | Out-Null
[void]$runspacePool.Close()
[void]$runspacePool.Dispose()
这将是并发的,总共大约需要10秒。如果计算机正常工作,它可能会在本地主机上运行三次
invoke-command comp1,comp2,comp3 { sleep 10; 'done' }
简单尝试api(线程):
你的剧本是什么?我相信远程计算机上的invoke命令已经在后台运行了。是的,但是invoke命令不能在这种环境中使用。我正在编写简单的函数来检查文件版本,或者剪切.log文件字符串,等等。。。这都是通过C$的份额,但现在每个周期都是一个接一个。。。对于500多台机器,它可能需要数小时。有很多方法可以在后台运行、作业、启动流程、工作流。。。嗨,你知道为什么当ping不成功时脚本会停止吗?我试图修改ping部分,当ping成功时,它只会将结果添加到$GH.results。无论哪种方式,它在第一台无法ping的机器上挂起而没有任何错误消息。
$a = [PowerShell]::Create().AddScript{sleep 5;'a done'}
$b = [PowerShell]::Create().AddScript{sleep 5;'b done'}
$c = [PowerShell]::Create().AddScript{sleep 5;'c done'}
$r1 = $a.BeginInvoke(); $r2 = $b.BeginInvoke() $r3 = $c.BeginInvoke()
$a.EndInvoke($r1); $b.EndInvoke($r2); $c.EndInvoke($r3)
a done
b done
c done