所以我有一个脚本,它将遍历并 ping 存储在 SQL Server 中的列表中的所有服务器。该脚本工作正常,但它按顺序执行所有操作(跛脚)。
有人可以帮助我了解如何将其更改为使用多线程而不是 foreach 循环吗?
$Server = "ServerName"
$Database = "DatabaseName"
$con = "server=$Server;database=$Database;Integrated Security=sspi"
$cmd = "SELECT ServerName FROM dbo.vwServerListActive"
$da = new-object System.Data.SqlClient.SqlDataAdapter ($cmd, $con)
$dt = new-object System.Data.DataTable
$da.fill($dt) | out-null
foreach ($srv in $dt)
{
$ping = new-object System.Net.NetworkInformation.Ping
$Reply = $ping.send($srv.ServerName)
$ServerName = $srv.ServerName
$ServerName
$Reply.status
if ($Reply.status –eq “Success”)
{
$sql = "UPDATE dbo.ServerList SET GoodPing = 1 WHERE GoodPing <> 1 AND ServerName = '$ServerName'"
}
else
{
$sql = "UPDATE dbo.ServerList SET GoodPing = 0 WHERE GoodPing <> 0 AND ServerName = '$ServerName'"
}
$Reply = ""
invoke-sqlcmd -serverinstance $Server -database $Database -query $sql
}
最佳答案
(根据 Chad Miller 的建议编辑 + 节流要求 + 等待作业修复 + STA 修复)
Support.ps1
powershell -File "Main.ps1" -Sta
Main.ps1
$Server = "ServerName"
$Database = "DatabaseName"
$con = "server=$Server;database=$Database;Integrated Security=sspi"
$cmd = "SELECT ServerName FROM dbo.vwServerListActive"
$da = New-Object System.Data.SqlClient.SqlDataAdapter -ArgumentList $cmd, $con
$dt = New-Object System.Data.DataTable
$da.Fill($dt) | Out-Null
$ThrottleLimit = 10
$activeJobs = New-Object 'System.Collections.Generic.List[Int32]'
$JobStateChanged = {
param (
[System.Object]$Sender,
[System.Management.Automation.JobStateEventArgs]$EventArgs
)
switch ($EventArgs.JobStateInfo.State)
{
Blocked { return }
Completed { $activeJobs.Remove($Sender.Id); break }
Failed { $activeJobs.Remove($Sender.Id); break }
NotStarted { return }
Running { return }
Stopped { $activeJobs.Remove($Sender.Id); break }
}
Unregister-Event -SourceIdentifier ("{0}.StateChanged" -f $Sender.Name)
}
foreach ($srv in $dt)
{
while ($true)
{
if ($activeJobs.Count -lt $ThrottleLimit)
{
$job = Start-Job -InitializationScript {
Add-PSSnapin -Name SqlServerCmdletSnapin100
} -ScriptBlock {
param (
[String]$Server,
[String]$Database,
[String]$ServerName
)
if (Test-Connection -ComputerName $ServerName -Quiet)
{
$sql = "UPDATE dbo.ServerList SET GoodPing = 1 WHERE GoodPing <> 1 AND ServerName = '$ServerName'"
}
else
{
$sql = "UPDATE dbo.ServerList SET GoodPing = 0 WHERE GoodPing <> 0 AND ServerName = '$ServerName'"
}
Invoke-SqlCmd -ServerInstance $Server -Database $Database -Query $sql
} -ArgumentList $Server, $Database, $srv.ServerName
$activeJobs.Add($job.Id)
Register-ObjectEvent -InputObject $job -EventName StateChanged -SourceIdentifier ("{0}.StateChanged" -f $job.Name) -Action $JobStateChanged
break
}
}
}
Get-Job | Where-Object { $_.State -eq "Running" } | Wait-Job
Get-Job | Remove-Job
关于sql - 多线程帮助/Powershell,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3239589/