gpt4 book ai didi

powershell - 使用 Start-Job 同时运行多个脚本 block (而不是循环)

转载 作者:行者123 更新时间:2023-12-04 22:07:06 25 4
gpt4 key购买 nike

大家好!

我一直在寻找一种方法来提高我的脚本的效率,我得出的结论是(在 StackOverflow 上的好人的帮助下)Start-Job 是可行的方法。

我有以下 foreach 循环,我想在 $servers 中的所有服务器上同时运行它。我在理解如何实际收集从 Receive-Job 返回的信息并将其添加到 $serverlist 时遇到问题。

PS:我知道我离解决这个问题还很远,但我真的很感激开始时的一些帮助,因为我对 Start-Job 和 Receive-Job 的工作方式感到非常困惑..

# List 4 servers (for testing)
$servers = Get-QADComputer -sizelimit 4 -WarningAction SilentlyContinue -OSName *server*,*hyper*

# Create list
$serverlistlist = @()

# Loop servers
foreach($server in $servers) {

# Fetch IP
$ipaddress = [System.Net.Dns]::GetHostAddresses($Server.name)| select-object IPAddressToString -expandproperty IPAddressToString

# Gather OSName through WMI
$OSName = (Get-WmiObject Win32_OperatingSystem -ComputerName $server.name ).caption

# Ping the server
if (Test-Connection -ComputerName $server.name -count 1 -Quiet ) {
$reachable = "Yes"
}

# Save info about server
$serverInfo = New-Object -TypeName PSObject -Property @{
SystemName = ($server.name).ToLower()
IPAddress = $IPAddress
OSName = $OSName
}
$serverlist += $serverinfo | Select-Object SystemName,IPAddress,OSName
}

注释
  • 我在脚本
  • 的末尾将 $serverlist 输出到一个 csv 文件
  • 我在我的完整脚本中列出了大约 500 个服务器
  • 最佳答案

    由于您的循环只需要处理一个字符串,因此很容易将其转换为并发脚本。

    下面是使循环使用后台作业来加速处理的示例。

    代码将遍历数组并启动后台作业以运行脚本块 $sb 中的代码。 $maxJobs 变量控制一次运行的作业数量,$chunkSize 变量控制每个后台作业将处理的服务器数量。

    在脚本块中添加您的其余处理,添加您想要返回到 PsObject 的任何其他属性。

    $sb = {
    $serverInfos = @()
    $args | % {
    $IPAddress = [Net.Dns]::GetHostAddresses($_) | select -expand IPAddressToString
    # More processing here...
    $serverInfos += New-Object -TypeName PsObject -Property @{ IPAddress = $IPAddress }
    }
    return $serverInfos
    }

    [string[]] $servers = Get-QADComputer -sizelimit 500 -WarningAction SilentlyContinue -OSName *server*,*hyper* | Select -Expand Name

    $maxJobs = 10 # Max concurrent running jobs.
    $chunkSize = 5 # Number of servers to process in a job.
    $jobs = @()

    # Process server list.
    for ($i = 0 ; $i -le $servers.Count ; $i+=($chunkSize)) {
    if ($servers.Count - $i -le $chunkSize)
    { $c = $servers.Count - $i } else { $c = $chunkSize }
    $c-- # Array is 0 indexed.

    # Spin up job.
    $jobs += Start-Job -ScriptBlock $sb -ArgumentList ( $servers[($i)..($i+$c)] )
    $running = @($jobs | ? {$_.State -eq 'Running'})

    # Throttle jobs.
    while ($running.Count -ge $maxJobs) {
    $finished = Wait-Job -Job $jobs -Any
    $running = @($jobs | ? {$_.State -eq 'Running'})
    }
    }

    # Wait for remaining.
    Wait-Job -Job $jobs > $null

    $jobs | Receive-Job | Select IPAddress

    这是每个作业处理单个服务器的版本:
    $servers = Get-QADComputer -WarningAction SilentlyContinue -OSName *server*,*hyper*

    # Create list
    $serverlist = @()

    $sb = {
    param ([string] $ServerName)
    try {
    # Fetch IP
    $ipaddress = [System.Net.Dns]::GetHostAddresses($ServerName)| select-object IPAddressToString -expandproperty IPAddressToString

    # Gather OSName through WMI
    $OSName = (Get-WmiObject Win32_OperatingSystem -ComputerName $ServerName ).caption

    # Ping the server
    if (Test-Connection -ComputerName $ServerName -count 1 -Quiet ) {
    $reachable = "Yes"
    }

    # Save info about server
    $serverInfo = New-Object -TypeName PSObject -Property @{
    SystemName = ($ServerName).ToLower()
    IPAddress = $IPAddress
    OSName = $OSName
    }
    return $serverInfo
    } catch {
    throw 'Failed to process server named {0}. The error was "{1}".' -f $ServerName, $_
    }
    }

    # Loop servers
    $max = 5
    $jobs = @()
    foreach($server in $servers) {
    $jobs += Start-Job -ScriptBlock $sb -ArgumentList $server.Name
    $running = @($jobs | ? {$_.State -eq 'Running'})

    # Throttle jobs.
    while ($running.Count -ge $max) {
    $finished = Wait-Job -Job $jobs -Any
    $running = @($jobs | ? {$_.State -eq 'Running'})
    }
    }

    # Wait for remaining.
    Wait-Job -Job $jobs > $null

    # Check for failed jobs.
    $failed = @($jobs | ? {$_.State -eq 'Failed'})
    if ($failed.Count -gt 0) {
    $failed | % {
    $_.ChildJobs[0].JobStateInfo.Reason.Message
    }
    }

    # Collect job data.
    $jobs | % {
    $serverlist += $_ | Receive-Job | Select-Object SystemName,IPAddress,OSName
    }

    关于powershell - 使用 Start-Job 同时运行多个脚本 block (而不是循环),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9601118/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com