使用Powershell在远程服务器上分发脚本级别作业

use*_*406 6 powershell

更多的理论问题......

我有一个存在于三台服务器上的powershell脚本.在此示例中,三个服务器是:

  1. 服务器1
  2. 服务器2
  3. server(服务器)

我正在使用另一台机器server4,使用Invoke-Command远程调用脚本C:\ ExampleScript.ps1,同时通过ComputerName参数指定远程机器.该脚本的最终目标是检测powershell是否正在运行,如果不是,则计算机"不忙"并且可以打开远程调用的脚本.如果计算机处于"忙碌状态",请移至下一台服务器并继续通过三台计算机,直到所有参数值都已耗尽.如果所有机器都很忙,那么如果有办法定期检查流程并查看它们是否仍处于打开状态,那将是理想的选择.以这种方式,脚本的执行可以在各种机器上以尽管原始的方式平衡.

请考虑以下代码:

$servers = "server1","server2","server3"
$data = "param1", "param2", "param3", "param4", "param5", "param6"

#somehow loop through the different servers/data using the above arrays
$job = Invoke-Command $servers[0] {
$ProcessActive = Get-Process powershell -ErrorAction SilentlyContinue
if($ProcessActive -eq $null)
{
    "Running"
    Invoke-Command -ComputerName $env:computername -FilePath C:\ExampleScript.ps1 -ArgumentList $data[0]
}
else
{
     "Busy go to next machine"
}
 } -AsJob 
Wait-Job $job 
$r = Receive-Job $job 
$r 
Run Code Online (Sandbox Code Playgroud)

试图实现的预期结果是尝试基于是否存在活动的PowerShell进程来跨机器来平衡脚本,如果不是移动到下一个机器并执行相同的测试和随后的可能执行.该脚本应该遍历$ data数组(或其他)中指定的所有值.

Neg*_*ath 5

我发现这个问题很有趣,所以我想尝试一下.

$servers = "server1","server2","server3"

$data = New-Object System.Collections.ArrayList
$data.AddRange(@("param1", "param2", "param3", "param4", "param5", "param6"))

$jobs = New-Object System.Collections.ArrayList

do 
{
    Write-Host "Checking job states." -ForegroundColor Yellow
    $toremove = @()
    foreach ($job in $jobs)
    {
        if ($job.State -ne "Running")
        {
            $result = Receive-Job $job

            if ($result -ne "ScriptRan")
            {
                Write-Host "  Adding data back to que >> $($job.InData)" -ForegroundColor Green
                $data.Add($job.InData) | Out-Null
            }

            $toremove += $job
        }
    }

    Write-Host "Removing completed/failed jobs" -ForegroundColor Yellow
    foreach ($job in $toremove)
    {
        Write-Host "  Removing job >> $($job.Location)" -ForegroundColor Green
        $jobs.Remove($job) | Out-Null
    }

    # Check if there is room to start another job
    if ($jobs.Count -lt $servers.Count -and $data.Count -gt 0)
    {
        Write-Host "Checking servers if they can start a new job." -ForegroundColor Yellow
        foreach ($server in $servers)
        {

            $job = $jobs | ? Location -eq $server
            if ($job -eq $null)
            {
                Write-Host "  Adding job for $server >> $($data[0])" -ForegroundColor Green
                # No active job was found for the server, so add new job
                $job = Invoke-Command $server -ScriptBlock {
                    param($data, $hostname)
                    $ProcessActive = Get-Process powershell -ErrorAction SilentlyContinue
                    if($ProcessActive -eq $null)
                    {
                        # This will block the thread on the server, so the JobState will not change till it's done or fails.
                        Invoke-Command -ComputerName $hostname -FilePath C:\ExampleScript.ps1 -ArgumentList $data
                        Write-Output "ScriptRan"
                    }
                } -ArgumentList $data[0], $env:computername -AsJob
                $job | Add-Member -MemberType NoteProperty -Name InData -Value $data[0]
                $jobs.Add($job) | Out-Null
                $data.Remove($data[0])
            }
        }
    }
    # Just a manual check of $jobs
    Write-Output $jobs
    # Wait a bit before checking again
    Start-Sleep -Seconds 10
} while ($data.Count -gt 0)
Run Code Online (Sandbox Code Playgroud)

基本上我创建一个数组,并为每个服务器保持不断填充一个作业.

新作业启动时,数据将从列表中删除,如果作业失败,则会将其添加回来.这是为了避免服务器运行具有相同数据/参数的脚本.

我目前缺乏适当的环境来测试这个问题,但是明天会在工作中给它一个旋转,如果需要的话,可以在任何更改时更新我的​​答案.