想要在多个实例中更新全局变量的Powershell脚本

时间:2018-07-05 12:25:26

标签: powershell

我现在正在创建构建服务器,并尝试并行运行构建,但是,当构建失败时,我希望发送一个全局变量标志来告诉其他构建服务器完成其构建,然后停止而不退出整个脚本。为此,我希望使用全局变量,但是当我从另一个脚本更改它时,似乎并没有对值进行更改。这是我必须查看的三个示例脚本:

这是并行调用其他两个脚本的主要脚本

$global:BUILD_FAILED = $false

function failBuild
{
    $global:BUILD_FAILED = $true
}

function buildHasFailed
{
    if ($global:BUILD_FAILED -eq $false)
    {
        return $false
    }
    else
    {
        return $true
    }
}

$test1 = Start-Job -Name "test1" -FilePath "C:\Users\username\Desktop\Untitled2.ps1"
$test2 = Start-Job -Name "test2" -FilePath "C:\Users\username\Desktop\Untitled3.ps1"

while ($test1.State -eq "Running" -or $test2.State -eq "Running")
{
    Receive-Job $test1
    Receive-Job $test2
}

Write-Host "Test0 finnish:"
$global:BUILD_FAILED
if (buildHasFailed)
{
    Write-Host "Fail"
    Exit 1
}

Write-Host "Pass"
Exit 0

这是两个脚本,用于测试如何在一个脚本中更改值并查看结果:

function failBuild
{
    $global:BUILD_FAILED = $true
}

function buildHasFailed
{
    if ($global:BUILD_FAILED -eq $false)
    {
        return $false
    }
    else
    {
        return $true
    }
}

Write-Host "Test2 started, $global:BUILD_FAILED"
buildHasFailed
Write-Host "Test2 sleeping 10s"
Start-Sleep -Milliseconds 10000
Write-Host "Test2 $global:BUILD_FAILED"
buildHasFailed

Exit 0

和:

function failBuild
{
    $global:BUILD_FAILED = $true
}

function buildHasFailed
{
    if ($global:BUILD_FAILED -eq $false)
    {
        return $false
    }
    else
    {
        return $true
    }
}

Write-Host "Test1 started, $global:BUILD_FAILED, sleeping 5s"
Start-Sleep -Milliseconds 5000
failBuild
Write-Host "Test1 ending, Status:"
buildHasFailed
$global:BUILD_FAILED

Exit 0

我当前的输出是:

Test1 started, , sleeping 5s
Test2 started, 
True
Test2 sleeping 10s
Test1 ending, Status:
True
True
Test2 
True
Test0 finnish:
False
Pass

我希望在test1将$ global:BUILD_FAILED设置为true之后,其余输出应该为false,但是不会更新。

有什么建议吗?

2 个答案:

答案 0 :(得分:1)

在Powershell中,每个作业都在新会话中运行。每个新会话都在新的全局范围内创建。 因此,您不能在作业之间使用全局变量。 一种选择可能是设置“ Machine”系统环境变量并使用该变量?

[Environment]::GetEnvironmentVariable("BUILD_FAILED", "Machine")

然后使用读取该值

[Environment]::SetEnvironmentVariable("BUILD_FAILED", $null, "Machine")

完成后删除此临时系统环境变量

(?:<)(?<=<)(\/?\w*)(?=.*(?<=<\/html))(?:>)

另一个适合您的选项是使用“运行空间”。我在这里https://learn-powershell.net/2013/04/19/sharing-variables-and-live-objects-between-powershell-runspaces/

为您找到了这篇文章

最后您可以选择编写包含全局值的文件吗?

答案 1 :(得分:0)

监视一个作业并在单个作业失败时终止其他作业可能更好,请参见下面的示例。

#Init
Clear-Host
$VerbosePreference = 'Continue'

#Special Function
Function Wait-BuildJob {
    Param(
        [Parameter(Mandatory=$true)]
        [ValidateNotNull()]
        $BuildJob
    )

    $BuildJob | Wait-Job -Any | ForEach-Object {

        if ($_.State -eq 'Failed') {
            # Show information about the 'Failed' Job.
            Write-Warning "Job $($_.Name) has $($_.State), stopping all remaining BuildJobs..."

            # Terminate all other Jobs.
            $BuildJob | Stop-Job


        }

        Else {
            # Show information about the current Job and remove the JobData.
            Write-Verbose "Job $($_.Name) retuned with state $($_.State)"
            $_ | Stop-Job -PassThru | Remove-Job
        }


        # Wait for further BuildJobs
        $RemainingBuildJobs = $BuildJob | Where-Object Id -ne $_.Id
        If ($RemainingBuildJobs) {

            Wait-BuildJob -BuildJob $RemainingBuildJobs
        }
    }

}

# ------------------------------------------------
#                    Script Start
# ------------------------------------------------
$ScriptStartDateTime = Get-Date

# A place to store the BuildJobs
$BuildJobs = @()

# Create a few dummy Jobs
1..4 | ForEach-Object {
    $BuildJobs += Start-Job -Name "Build$($_)" -ScriptBlock {
        Start-Sleep -Seconds 60
    }
}

# Create a Job that should fail
$BuildJobs += Start-Job -Name Build5 -ScriptBlock {
    Start-Sleep -Seconds 5
    throw "build failed somehow"
    Start-Sleep -Seconds 60
}

# Create some more dummy Jobs
6..10 | ForEach-Object {
    $BuildJobs += Start-Job -Name "Build$($_)" -ScriptBlock {
        Start-Sleep -Seconds 60
    }
}

# Wait for BuildJobs to complete.
Wait-BuildJob -BuildJob $BuildJobs

# Show Runtime for Build
$RunTime = (Get-date) - $ScriptStartDateTime
Write-Verbose "Total RunTime in Secconds: $($RunTime.TotalSeconds)"

作业失败的示例输出:

WARNING: Job Build5 has Failed, stopping all remaining BuildJobs...
VERBOSE: Job Build1 retuned with state Stopped
VERBOSE: Job Build2 retuned with state Stopped
VERBOSE: Job Build3 retuned with state Stopped
VERBOSE: Job Build4 retuned with state Stopped
VERBOSE: Job Build6 retuned with state Stopped
VERBOSE: Job Build7 retuned with state Stopped
VERBOSE: Job Build8 retuned with state Stopped
VERBOSE: Job Build9 retuned with state Stopped
VERBOSE: Job Build10 retuned with state Stopped
VERBOSE: Total RunTime in Secconds: 5.943828

没有失败的作业的示例输出:

VERBOSE: Job Build1 retuned with state Completed
VERBOSE: Job Build2 retuned with state Completed
VERBOSE: Job Build3 retuned with state Completed
VERBOSE: Job Build4 retuned with state Completed
VERBOSE: Job Build5 retuned with state Completed
VERBOSE: Job Build6 retuned with state Completed
VERBOSE: Job Build7 retuned with state Completed
VERBOSE: Job Build8 retuned with state Completed
VERBOSE: Job Build10 retuned with state Completed
VERBOSE: Job Build9 retuned with state Completed
VERBOSE: Total RunTime in Secconds: 61.9364418