代码之家  ›  专栏  ›  技术社区  ›  VA systems engineer

为什么传入脚本块的参数无法工作?

  •  0
  • VA systems engineer  · 技术社区  · 7 年前

    充分披露:我的问题可能是基于对Citrix PowerShell module for Xen Desktop的不完全理解。

    我有下面的脚本块。它在循环中被调用,对于列表中的每个VM调用一次。我在用 PowerShell Jobs 因为我想让UI线程保持自由,以便在作业运行时更新UI。

    代码“A”

    $j = Start-Job -Name $jobName -ScriptBlock {
        param($url, $uuid, $cred, $snapshotName)
        $ErrorActionPreference = "Stop" 
        try
        {
            $error.clear()
            $xSS = $cred | Connect-XenServer -url $url -NoWarnCertificates -SetDefaultSession -PassThru; 
            $vm = (Get-XenVM -SessionOpaqueRef $xss.opaque_ref -uuid $uuid)
            #Create snapshot
            Invoke-XenVM -Async -SessionOpaqueRef $xss.opaque_ref -VM $vm -XenAction Snapshot -NewName $snapshotName
            return "OK"
        }
        catch
        {
            return ("ERROR: "+$error)
        }
    } -ArgumentList $global:configFileVmMetaData.poolUrl, $xenVm.key, $global:cred, $snapshotName
    

    代码“A” Connect-XenServer 每次调用脚本块时使用cmdlet。

    所以,我试着打电话 连接XenServer 一旦跳出循环并传入session变量,如中所示 代码“B” . 结果是错误 Could not find open sessions to any XenServers 在脚本块中抛出。我假设$xss会话变量在传递到脚本块时受到了某种影响。

    代码“B”

    $xSS = $cred | Connect-XenServer -url $global:configFileVmMetaData.poolUrl -NoWarnCertificates -SetDefaultSession -PassThru; 
    
    loop
    {
    
        $j = Start-Job -Name $jobName -ScriptBlock {
            param($xss, $uuid, $snapshotName)
            $ErrorActionPreference = "Stop" 
            try
            {
                $error.clear()
                $vm = (Get-XenVM -SessionOpaqueRef $xss.opaque_ref -uuid $uuid)
                #Create snapshot
                Invoke-XenVM -Async -SessionOpaqueRef $xss.opaque_ref -VM $vm -XenAction Snapshot -NewName $snapshotName
                return "OK"
            }
            catch
            {
                return ("ERROR: "+$error)
            }
        } -ArgumentList $xss, $xenVm.key, $snapshotName
    
    }
    

    Robert Cotterman 回答

    Could not find open sessions to any XenServers

    仅供参考-使用PowerShell 5.1

    示例使用 $using . 变量内容按预期传入和传出

    cls
    
    $aLocal = "AAA"
    $bLocal = "BBB"
    
    $j = Start-Job -Name "TestJob" -ScriptBlock {
        return ($using:aLocal + " *** " + $using:bLocal)
        }
    
    while ($true)
    {
        $g = get-job -name "TestJob"
    
        write-host ("get-job " + $g.Name + " is " + $g.State)
    
        if ($g.State -ne "Running")
        {
            break
        }
    
        start-sleep -Seconds 1
    }
    
    write-host ("receive-Job='" + (receive-Job -Name "TestJob") +"'")
    
    $g = get-Job -Name "TestJob"
    Write-Host ("get-Job "+$g.name + " " + $g.state + " " + $g.HasMoreData + " " + $g.id)
    
    if($g)
    {
        Remove-Job -Name "TestJob"
    }
    

    输出

    get-job TestJob is Running
    get-job TestJob is Completed
    receive-Job='AAA *** BBB'
    get-Job TestJob Completed False 45
    Remove-Job
    

    cls
    
    $aLocal = "AAA"
    $bLocal = "BBB"
    
    $j = Start-Job -Name "TestJob" -ScriptBlock {
        return ($args[0] + " *** " + $args[1])
        } -ArgumentList ($aLocal, $bLocal)
    
    while ($true)
    {
        $g = get-job -name "TestJob"
    
        write-host ("get-job " + $g.Name + " is " + $g.State)
    
        if ($g.State -ne "Running")
        {
            break
        }
    
        start-sleep -Seconds 1
    }
    
    write-host ("receive-Job='" + (receive-Job -Name "TestJob") +"'")
    
    $g = get-Job -Name "TestJob"
    Write-Host ("get-Job "+$g.name + " " + $g.state + " " + $g.HasMoreData + " " + $g.id)
    
    if($g)
    {
        Remove-Job -Name "TestJob"
    }
    

    输出

    get-job TestJob is Running
    get-job TestJob is Completed
    receive-Job='AAA *** BBB'
    get-Job TestJob Completed False 49
    

    使用命名参数的示例。变量内容按预期传入和传出

    cls
    
    $aLocal = "AAA"
    $bLocal = "BBB"
    
    $j = Start-Job -Name "TestJob" -ScriptBlock {
        param($a, $b)
        return ($a + " *** " + $b)
        } -ArgumentList ($aLocal, $bLocal)
    
    while ($true)
    {
        $g = get-job -name "TestJob"
    
        write-host ("get-job " + $g.Name + " is " + $g.State)
    
        if ($g.State -ne "Running")
        {
            break
        }
    
        start-sleep -Seconds 1
    }
    
    write-host ("receive-Job='" + (receive-Job -Name "TestJob") +"'")
    
    $g = get-Job -Name "TestJob"
    Write-Host ("get-Job "+$g.name + " " + $g.state + " " + $g.HasMoreData + " " + $g.id)
    
    if($g)
    {
        Remove-Job -Name "TestJob"
    }
    

    输出

    get-job TestJob is Running
    get-job TestJob is Completed
    receive-Job='AAA *** BBB'
    get-Job TestJob Completed False 55
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   TheMadTechnician    7 年前

        2
  •  1
  •   Robert Cotterman    7 年前

    作业和invoke命令要求您指定使用的是变量。只需将变量从

    $variable
    

    $using:variable
    

    内部变量不需要这个。但是从父脚本调用变量就可以了。

    或者,由于您将$xss作为参数传递,因此您不会使用$xss调用它,而是使用

    $args[0]
    

    原因是整个xss变量作为参数打印,而不是在作业中命名。它被命名为$args,并在第一个插槽(0)中有一个位置。

    我更喜欢$using:variable as 它减少了混乱