使用Invoke-Command / Start-Job和PSRemoting

时间:2016-04-23 19:14:09

标签: powershell powershell-remoting

我正在处理一个脚本,该脚本可以远程转换为一系列服务器并执行来自一系列PoSh功能的命令。我需要保留同步处理,并且只想添加在函数上执行异步操作的功能。

如何使用Start-JobInvoke-Command -AsJob将其转换为主要功能作为作业?这些函数是PowerShell模块的一部分,如果这会产生影响。

我已经尝试过我在这里看过的几个不同的例子,但他们似乎并没有真正处理这个功能。

例如,对于以下功能,我尝试过:

foreach($s in $servers)
{
            if($lbFileLocation -eq $true)
            {
                #Rename-LoadBalancerFile -ServerName $server -Revert $false -filePath $filePath -cred $cred - #sync function works great
                Start-Job -Name 'RenLb'  -InitializationScript {Import-Module '.\Down.psm1'} $ScriptBlock -ArgumentList $server,$false,$lbFileLocation,$Cred | Out-Null
            }
 }

        Write-Host 'Waiting for LB rename.'
        While (Get-Job -Name 'RenLb' | where { $_.State -eq 'Running' } )
              {
                  Start-Sleep 1
              }

             Write-Host 'completed'

原创,同步功能:

function Rename-LoadBalancerFile
{
    param
    (
        [string]
        [Parameter(Mandatory=$true)]
        $ServerName,
        [bool]
        [Parameter(Mandatory=$true)]
        $Revert,
        [string]
        [Parameter(Mandatory=$true)]
        $filePath,
        [PSCredential]
        [Parameter(Mandatory=$false)]
        $cred
    )

    $scriptBlock = {
        param
        (
            [bool]
            [Parameter(Mandatory=$true)]
            $Revert,
            [string]
            [Parameter(Mandatory=$true)]
            $filePath
        )

        if(Test-Path $filePath -eq $true)
        {
            Write-Host 'file tested true'
            if($Revert -eq $true)
            {
                $fileName = [IO.Path]::GetFileName($filePath)
                $directory = [IO.Path]::GetDirectoryName($filePath)

                Rename-Item -Path "$directory\file.txt" -NewName $fileName
            }
            else
            {
                Rename-Item -Path $filePath -NewName 'file.txt'
            }
        }
    }

    $session = New-PSSession -ComputerName $ServerName -Authentication Credssp -Credential $cred
    Invoke-Command -Session $session -ScriptBlock $scriptBlock -ArgumentList $Revert, $filePath
    Remove-PSSession $session
}

1 个答案:

答案 0 :(得分:1)

  1. Import-Module .\down.psm1可能会失败,因为Start-Job没有与您的脚本相同的工作目录,因此您需要更改工作目录或使用模块的绝对路径。
  2. $scriptblock中的Start-Job是什么?它从未创造过。请注意,$scriptblock需要使用$args[0] , $args[1] ..来访问使用-ArgumentList传递的值,或者在scriptblock的开头定义参数(param($server,$filepath...))。
  3. 您可以尝试这样的事情:

    #Get full path for module
    $module = Resolve-Path ".\Down.psm1"
    
    #Create scriptblock
    $scriptblock = { Rename-LoadBalancerFile -ServerName $args[0] -Revert $args[1] -filePath $args[2] -cred $args[3] }
    
    foreach($s in $servers)
    {
        Start-Job -Name "RenLb" -InitializationScript ([scriptblock]::Create("Import-Module $module")) -ScriptBlock $scriptblock -ArgumentList $s,$false,$lbFileLocation,$Cred | Out-Null
    }
    
    Write-Host 'Waiting for LB rename.'
    
    While (Get-Job -Name 'RenLb' | where { $_.State -eq 'Running' } )
    {
        Start-Sleep 1
    }
    
    Write-Host 'completed'
    

    我使用([scriptblock]::Create("Import-Module $module"))生成InitializationScript以确保$module - 变量已扩展为文件路径,因为$module在新作业线程中不可用。如果要对模块路径进行硬编码,可以将其替换为-InitializationScript { Import-Module c:\mymodule\down.psm1 }