Почему аргумент, переданный в блок скрипта, не работает? - PullRequest
0 голосов
/ 05 октября 2018

Полное раскрытие. Моя проблема может быть связана с неполным пониманием модуля Citrix PowerShell для Xen Desktop.

У меня есть следующий блок скриптов.Он вызывается в цикле, один раз для каждой виртуальной машины в списке.Я использую PowerShell Jobs, поскольку хочу, чтобы поток пользовательского интерфейса оставался свободным для обновления пользовательского интерфейса во время выполнения заданий.

Код "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 каждый раз, когда вызываю блок скрипта.

Итак, я попытался вызвать Connect-XenServer после выхода из цикла и передачи переменной сеанса, как показано ниже в Код "B" .В результате была выдана ошибка Could not find open sessions to any XenServers внутри блока скрипта.Я предполагаю, что переменная сеанса $ xss как-то колеблется, когда она передается в блок скрипта.

Есть идеи, почему переменная $ 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 ]

0 голосов
/ 08 октября 2018

Я просто не думаю, что это так работает.Соединение с сервером Xen создается для сеанса PowerShell, а информация об этом соединении собирается в переменной $ xss.Каждое задание запускает собственный сеанс PowerShell.Так что просто передача $ xss на работу - это не то же самое, это просто описание деталей подключения.

0 голосов
/ 08 октября 2018

Jobs и invoke-command требуют, чтобы вы указали, что вы используете свою переменную.Просто измените переменную с

$variable

на

$using:variable

Внутренние переменные не нуждаются в этом.Но вызов переменных из родительского скрипта делают.

В качестве альтернативы, поскольку вы передаете $ xss в качестве аргумента, вы бы не называли его с помощью $ xss, а скорее

$args[0]

, поскольку это ваш первый аргумент.И $ args [1] для второго и т. Д. Причина в том, что вся переменная xss печатается в качестве аргумента и не именуется внутри задания.Ему присвоено имя $ args, и он находится в первом слоте (0).

Я предпочитаю использовать $: переменная, поскольку это уменьшает путаницу

...