【问题标题】:Powershell SSH / run on multiple machine simultaneouslyPowershell SSH /同时在多台机器上运行
【发布时间】:2022-08-06 19:24:48
【问题描述】:

我有这个脚本;现在我编写脚本,它会一个接一个地遍历每台机器。我怎样才能让所有 ips 同时运行脚本在 \'ip.txt\' 谢谢。

$Computers = $Computers = Get-Content -Path .\\ip.txt | Where-Object { $_ -match \'\\S\' }

foreach($Computer in $Computers){
Write-Host $Computer

    $User = \"-\"
    $Password = \"-\"
    $Command = \'hostname\'

    $secpasswd = ConvertTo-SecureString $Password -AsPlainText -Force
    $Credentials = New-Object System.Management.Automation.PSCredential($User, $secpasswd)

Get-SSHTrustedHost | Remove-SSHTrustedHost

$SessionID = New-SSHSession -ComputerName $Computer -Credential $Credentials -AcceptKey:$true

Invoke-SSHCommand -Index $sessionid.sessionid -Command $Command | Select -Expand Output | Add-Content -Path result.txt
}

    标签: powershell ssh


    【解决方案1】:

    我假设 Invoke-SSHCommand 来自 PoshSSH 模块。如果是这样,帮助文档没有“-AsJob”参数或任何会导致它在后台运行的东西。

    因此,您需要在脚本中使用 PowerShell 作业来一次调用多个命令。这是一个标准的 PowerShell 作业类型的问题,因此在这里回答它可能有点多余。

    $scriptBlock = {
        # You must pass any parameters that you want to use in your script block
        param(
            [String]$Computer,
            [System.Management.Automation.PSCredential]$Credentials,
            [String]$Command
        )
        $SessionID = New-SSHSession -ComputerName $Computer -Credential $Credentials -AcceptKey:$true
    
        if ($SessionID)
        {
            # Any output that the Invoke-SSHCommand outputs will be allowed
            # to escape to the pipeline here because we don't assign the output
            # to a variable.  When you call Receive-Job, you will then get all of
            # the output that escaped to the pipeline (i.e. you will get the return
            # value of this command)
            Invoke-SSHCommand -Index $sessionid.sessionid -Command $Command
        }
        else
        {
            # Or provide your own error handling
            return "Could not create Session"
        }
    }
    
    # I'm confused what this does and if you need to call it each loop, or just once
    Get-SSHTrustedHost | Remove-SSHTrustedHost
    
    $Computers = Get-Content -Path .\ip.txt | Where-Object { $_ -match '\S' }
    
    $hashTableOfJobs= @{}
    foreach($Computer in $Computers) 
    {
        Write-Host $Computer
    
        $User = "-" #ToDo, add username
        $Password = "-" #ToDo, add password
        $Command = 'hostname'
    
        $secpasswd = ConvertTo-SecureString $Password -AsPlainText -Force
        $Credentials = New-Object System.Management.Automation.PSCredential($User, $secpasswd)
    
        # This next line would have a problem if you had duplicates in your list 
        # of computers (because the HashTable needs keys to be unique)
    
        # Also note that the "Argument List" needs to provide the exact
        # arguments defined in your Script Block in the same order.
        $hashTableOfJobs["$computer"] = Start-Job -ScriptBlock $scriptBlock -ArgumentList @($Computer, $Credentials, $Command)
    
        # Name is just a string for you to identify the job; I find it helpful later
        $hashTableOfJobs["$computer"].Name = "$Computer"
    }
    
    # At this point, $hashTableOfJobs contains a bunch of jobs that have been 
    # run (or are still running).  We need to let all the jobs finish before
    # we continue.
    
    # A more sophisticated approach could loop through $listOfJobs and check
    # the "State" of the job, and then write status and decide to wait longer
    # To do that, check if ($_.State -like "*Running*")
    
    # Option 1 for waiting for jobs
    # Wait with a timeout of 10 seconds
    $finishedJobs = $hashTableOfJobs.Values | Wait-Job -Timeout 10
    
    # Option 2 for waiting for jobs
    #     Left as a coding exercise for you =)
    
    if ($finishedJobs.Count -ne $hashTableOfJobs.Count)
    {
        # ToDo, some of your jobs didn't finish. Add error handling.
        Write-Warning "$($finishedJobs.Count) out of $($hashTableOfJobs.Count) jobs finished."
        # If your script is running on a lot of hosts and you don't plan to
        # close and restart the PowerShell window, then it is important to
        # clean up your job objects using the Stop-Job and Remove-Job cmdlets
    }
    
    # For below, you have to choose between Option 1 and Option 2.
    # If you call "Receive-Job" twice, then you will only get output
    # the first time you call it.
    
    # Option 1 for receiving jobs: Look at only the finished jobs
    foreach ($job in $finishedJobs)
    {
        Write-Host "Receiving output for the $($job.Name) job"
        $thisJobOutput = Receive-Job -Job $job
        Write-Host "$thisJobOutput"
        Write-Host ""
    }
    
    # Option 2 for receiving jobs: Look at all jobs
    foreach ($computer in $hashTableOfJobs.Keys)
    {
        $job = $hashTableOfJobs[$computer]
        Write-Host "Receiving output for the $computer ($($job.Name)) job (state = $($job.State))"
        if ($job.State -like "*Running*")
        {
            Write-Warning "Oops, $($job.Name) on computer $computer didn't finish"
        }
        else
        {
            $thisJobOutput = Receive-Job -Job $job
            # Note, if you've already called Receive-Job, then you won't
            # get any more output, and this will be blank.  (We called 
            # "Receive-Job" above.  Delete that call and this will work)
            Write-Host "$thisJobOutput"
            Write-Host ""
        }
    }
    
    # Clean up job objects to prevent memory leak
    $hashTableOfJobs.Values | Remove-Job
    

    【讨论】:

      【解决方案2】:

      首先,将foreach 循环中的代码放入scriptblock。您可能需要进行一些细微的调整。

      然后,您可以将此代码块传递给Invoke-Command-ScriptBlock 参数,并将$Computers 的数组传递给-ComputerName 参数。这将允许您同时针对多台计算机并行运行脚本块。如果您需要一次限制多少个,可以使用-ThrottleLimit 参数。

      Invoke-Command 文档中的示例 13 还显示了在多台计算机上同时运行“脚本”的另一种方法,如果您想避免使用脚本块。

      【讨论】:

        猜你喜欢
        • 2022-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-09
        • 2015-09-08
        • 2013-08-26
        • 1970-01-01
        • 2014-04-07
        相关资源
        最近更新 更多